Skip to content

意图

孪生模式是一种设计模式,它提供了一个标准的解决方案来模拟java中的多重继承

解释

真实世界例子

考虑一个球类的游戏,它需要两种类型的特征,游戏项目和线程功能才能运行 想要在游戏中顺畅,我们可以使用两个对象,一个对象与第一种类型兼容,另一个与第二种类型兼容。 这对对象可以在游戏中充当一个球。

通俗地说

它提供了一种方法来形成两个紧密耦合的子类,这些子类可以充当具有两端的孪生类。

维基百科说

在软件工程中,孪生模式是一种软件设计模式,它允许开发人员在不支持多重继承的编程语言中对多重继承进行建模。这种模式避免了多重继承的许多问题。

程序示例

以我们上面的游戏球为例。考虑我们有一个游戏,其中球需要既是“GameItem”又是“Thread”类。首先,我们有下面给出的 GameItem 类和 Thread

java

@Slf4j
public abstract class GameItem {

  public void draw() {
    LOGGER.info("draw");
    doDraw();
  }

  public abstract void doDraw();


  public abstract void click();
}

然后,我们有子类 BallItemBallThread 分别继承它们。

java

@Slf4j
public class BallItem extends GameItem {

  private boolean isSuspended;

  @Setter
  private BallThread twin;

  @Override
  public void doDraw() {

    LOGGER.info("doDraw");
  }

  public void move() {
    LOGGER.info("move");
  }

  @Override
  public void click() {

    isSuspended = !isSuspended;

    if (isSuspended) {
      twin.suspendMe();
    } else {
      twin.resumeMe();
    }
  }
}


@Slf4j
public class BallThread extends Thread {

  @Setter
  private BallItem twin;

  private volatile boolean isSuspended;

  private volatile boolean isRunning = true;

  /**
   * Run the thread.
   */
  public void run() {

    while (isRunning) {
      if (!isSuspended) {
        twin.draw();
        twin.move();
      }
      try {
        Thread.sleep(250);
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
    }
  }

  public void suspendMe() {
    isSuspended = true;
    LOGGER.info("Begin to suspend BallThread");
  }

  public void resumeMe() {
    isSuspended = false;
    LOGGER.info("Begin to resume BallThread");
  }

  public void stopMe() {
    this.isRunning = false;
    this.isSuspended = true;
  }
}

现在,当我们需要球时,我们可以实例化 BallThreadBallItem 的一对对象,并将它们传递给它的对象,以便它们可以适当地一起行动。

java

var ballItem = new BallItem();
var ballThread = new BallThread();

ballItem.setTwin(ballThread);
ballThread.setTwin(ballItem);

类图

alt text

适用性

使用孪生模式当

  • 在不支持此功能的语言中模拟多重继承。
  • 避免多重继承的某些问题,例如名称冲突。

鸣谢