设计模式 - 中介者模式

中介者模式:用中介对象来封装一系列对象的交互,使各对象不需要显式地相互依赖,松散耦合,使类的改动局限于类本身和中介类
核心:星型拓扑,由中介者作为通信中枢(一中介者:多同事类,同事类之间解除依赖)
角色:

  • 具体中介类Mediator:作为所有同事类的依赖,作为通信中枢。
  • 具体同事类Colleague:执行功能逻辑,以及与中介类进行交互(从而实现与其他同事的交互)。

PS:需根据业务场景决定,是否需要抽象出同事类的共性接口。

general

// 最基本的中介者模式,Mediator完成通信转发的职责
public class Mediator {
    private ConcreteColleageA concreteColleageA = new ConcreteColleageA(this);
    private ConcreteColleageB concreteColleageB = new ConcreteColleageB(this);

    public void doMethodA() {
        System.out.print("Mediator call -> ");
        concreteColleageA.selfMethodA();
    }

    public void doMethodB() {
        System.out.print("Mediator call -> ");
        concreteColleageB.selfMethodB();
    }
}
// 同事抽象,封装共性(当同事对象各有不同功能时,具体功能只能由子类自行实现,而无法作为共性封装)
public abstract class Colleage {
    // 同事类需要持有中介者的引用,通过中介者实现与其他同事类的交互
    protected Mediator mediator;

    protected Colleage(Mediator mediator){
        this.mediator = mediator;
    }
}

public class ConcreteColleageA extends Colleage{
    protected ConcreteColleageA(Mediator mediator) {
        super(mediator);
    }

    // 自有方法,由类自己实现
    public void selfMethodA(){
        System.out.println("ColleageA - Do method A!");
    }

    // 依赖方法,需要调用其他类实现(在中介者模式中,通知中介类,由中介类去协调处理)
    public void dependenceMethodB(){
        System.out.print("ColleageA call method B-> ");
        mediator.doMethodB();
    }
}
// 功能不同的同事,由中介者实现消息转发 ---》 使同事类之间解耦(网状 -》 星状) --- 实例:服务治理
// 使同事类的改动范围限制在自身和中介类中, 弊端:中介类可能会很复杂。
public class Test {
    public static void main(String[] args) {
        Mediator mediator = new Mediator();
        ConcreteColleageA concreteColleageA = new ConcreteColleageA(mediator);
        ConcreteColleageB concreteColleageB = new ConcreteColleageB(mediator);

        concreteColleageA.dependenceMethodB();  // ColleageA call method B-> Mediator call -> ColleageB - Do method B!
        concreteColleageA.selfMethodA();        // ColleageA - Do method A!

        concreteColleageB.dependenceMethodA();  // ColleageB call method A-> Mediator call -> ColleageA - Do method A!
        concreteColleageB.selfMethodB();        // ColleageB - Do method B!
    }
}

ChatRoom

// 一种较为特殊的中介者模式,此时,中介者行使一种平台的功能,所有用户均与平台进行操作。
public class ChatRoom {
    List<Message> messages = new ArrayList<>();

    public void receive(User user, String message){
        messages.add(new Message(user.getUsername(), new Date(), message));
    }

    public void show(){
        for(Message message : messages){
            System.out.println(message.username + "   " + CommonUtils.simpleFormatDate(message.date) + "\n" + message.message);
        }
    }

    // 封装的消息对象,只有ChatRoom可以操作
    private class Message {
        private String username;
        private Date date;
        private String message;

        public Message(String username, Date date, String message) {
            this.username = username;
            this.date = date;
            this.message = message;
        }
    }
}
public class User {
    private String username;

    public User(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void chat(ChatRoom chatRoom, String message){
        chatRoom.receive(this,message);
    }
}
// 中介者作为平台,为所有同事对象提供平台的功能。(同事只需和中介者交互)
public class Test {
    public static void main(String[] args) {
        ChatRoom chatRoom = new ChatRoom();
        User userA = new User("kiqi");
        User userB = new User("xike");

        userA.chat(chatRoom,"你啥时候放假?");
        userB.chat(chatRoom,"不知道啊,下周四吧");
        userA.chat(chatRoom,"这样吗,好早啊,我这都没下通知!!!");
        userB.chat(chatRoom,"哦,这样子的老板,炒了吧,我养你!");

        chatRoom.show();
    }
}

简化服务治理

// 中介者,维护所有的服务列表,同时负责转发服务请求
public class Mediator {
    // 服务管理者只能有一份,使用单例模式创建
    private final static Mediator mediator = new Mediator();

    private Mediator() {}

    public static Mediator getInstance(){
        return mediator;
    }

    // 维护所有的服务列表<serviceId, service实例>
    private Map<String, AbstractService> serviceMap = new HashMap<>();

    // 服务需要注册到Mediator中,才能被其他服务调用
    public final void register(String serviceId, AbstractService service){
        serviceMap.put(serviceId, service);
    }

    // 根据serviceId查找对应的服务对象,并将调用方法名和参数传递过去
    public Object relay(String serviceId, String method, Object[] params){
        System.out.println("Mediator.relay() - " + serviceId + "." + method + "()");
        if (serviceMap.containsKey(serviceId)) {
            AbstractService service = serviceMap.get(serviceId);
            return service.receive(method, params);
        }
        return null;
    }
}
// 抽象服务类,共性:均需注册到Mediator中,且,需要一个统一的接口作为请求的入口(在Spring中,为Dispatcher类)
public abstract class AbstractService {
    protected abstract void register();

    protected abstract Object receive(String methodId, Object[] params);
}

// 服务B 提供展示功能,同时调用服务A 执行记录
public class ServiceB extends AbstractService{
    private Mediator mediator;

    public ServiceB(){}

    @Override
    protected void register() {
        mediator = Mediator.getInstance();
        mediator.register("ServiceB",this);
    }

    @Override
    protected Object receive(String methodId, Object[] params) {
        if("show".equals(methodId)){
            show(params);
        }
        return null;
    }

    private void show(Object[] params){
        System.out.println("ServiceB - 执行ServiceB.show功能");
        System.out.println("ServiceB - 申请serviceA.record()方法");
        mediator.relay("ServiceA","record",params);
    }
}
public class Test {
    public static void main(String[] args) {
        Mediator mediator = Mediator.getInstance();
        new ServiceA().register();
        new ServiceB().register();

        mediator.relay("ServiceB","show",new Object[]{"String"});
    }
}

// Mediator.relay() - ServiceB.show()
// ServiceB - 执行ServiceB.show功能
// ServiceB - 申请serviceA.record()方法
// Mediator.relay() - ServiceA.record()
// ServiceA - 执行ServiceA.record功能
posted @ 2020-12-03 00:22  祁奇  阅读(67)  评论(0编辑  收藏  举报