设计模式学习笔记(13)中介者

本文实例代码:https://github.com/JamesZBL/java_design_patterns

中介者(Mediator)模式是用来降低多个对象和类之间的通信复杂性的。这种模式中通常提供一个充当中介者角色的类,用来承担“中心化”或“集中化”的职能,与各个对象之间都可以分别相互通信,它的一大优势是减少或避免其他对象之间的互相通信,在通信方面降低了耦合度。

实例

现在要举行一场派对,派对中会穿插各种游戏活动,凡是参加派对的人都要到派对举办者那里登记。并且,每次有参与者想要参加派对中的某个活动的时候都要先向派对举办者提出请求,由举办者来批准他的请求,然后这个活动才开始进行。

先定义派对举办者行为的接口,举办者的职责有邀请成员加入和批准成员参加活动

Party.java

public interface Party {

  void addMember(PartyMember member);

  void letAct(PartyMember member, Activity activity);
}

然后是派对成员的接口,成员的职责有参加派对、提出参加活动的请求以及参加活动

PartyMember.java

public interface PartyMember {

  void joinParty(Party party);

  void partyActivity(Activity activity);

  void act(Activity activity);
}

再定义一个类来具体实现派对举办者功能

PartyImpl.java

public class PartyImpl implements Party {

  private List<PartyMember> members;

  public PartyImpl() {
    members = new ArrayList<>();
  }

  @Override
  public void addMember(PartyMember member) {
    members.add(member);
    member.joinParty(this);
  }

  @Override
  public void letAct(PartyMember member, Activity activity) {
    for (PartyMember m : members) {
      if (!member.equals(m)) {
        m.partyActivity(activity);
      }
    }
  }
}

定义一个派对实现成员接口的抽象类,保留一个 toString() 抽象方法,留到其具体子类中实现

AbstractPartyMember.java

public abstract class AbstractPartyMember implements PartyMember {

  private static final Logger LOGGER = LoggerFactory.getLogger(AbstractPartyMember.class);

  private Party party;

  @Override
  public void joinParty(Party party) {
    LOGGER.info("{}加入了派对", this);
    this.party = party;
  }

  @Override
  public void act(Activity activity) {
    if (null != activity) {
      LOGGER.info("{}提议进行{}活动", this, activity);
      party.letAct(this, activity);
    }
  }

  @Override
  public void partyActivity(Activity activity) {
    LOGGER.info("进行派对活动,名称:{},介绍:{}", activity, activity.getDescription());
  }

  @Override
  public abstract String toString();
}

派对中提供的活动有射击、猜灯谜、桌游和唱歌,为其定义一个枚举类

Activity.java

public enum Activity {
  SHOOT("射击", "Shooting"), GUESS("猜灯谜", "Guess"), DESKTOP_GAME("桌游", "Desktop games"), SING("唱歌", "singing");

  private String name;
  private String description;

  Activity(String name, String description) {
    this.name = name;
    this.description = description;
  }

  public String getDescription() {
    return description;
  }

  @Override
  public String toString() {
    return name;
  }
}

有四种不同职业或特点的参与者,分别继承自 AbstractPartyMember 类,分别覆盖了父类中的 toString() 方法来表示其特征

他们分别是 Officer.java,Oldman.java,Student.javaBusinessman.java,此处省略具体代码

现在来举办一次派对,参与者们分别向派对举办者提出活动请求,举办者分别批准

App.java

public class Application {

  private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);

  public static void main(String[] args) {
    //   派对举办者
    Party party = new PartyImpl();
    // 学生
    Student student = new Student();
    // 官员
    Officer officer = new Officer();
    // 商人
    Businessman businessman = new Businessman();
    // 老人
    Oldman oldman = new Oldman();

    // 邀请成员加入
    party.addMember(student);
    party.addMember(officer);
    party.addMember(businessman);
    party.addMember(oldman);

    // 分别提出参加活动的请求
    student.act(Activity.DESKTOP_GAME);
    officer.act(Activity.GUESS);
    businessman.act(Activity.SHOOT);
    oldman.act(Activity.SING);
  }
}

总结

需要使用中介者模式的场景是对象与对象之间存在大量的关联关系,这样下去会导致系统的结构变得复杂,一个对象的改动势必会影响到另一个与之关联的对象,,同时做出相应的改动,它们之间分别相互耦合,几乎形成了“网状”的结构,这对于复杂的系统是非常不利的。

中介者模式可以将这种 “网状结构” 解耦形成 “星形结构”,最典型的应用实例就是 MVC 结构,其中的 C (控制器) 就担当了 V(视图)和 M(模型)之间的中介者。

中介者模式的缺点是会使中介者对象异常复杂,降低了可维护性,所以应当尽量避免在对象间的职责划分比较难以界定的场景中使用。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.