外观模式与中介模式的区别

发布于:2024-12-20 ⋅ 阅读:(15) ⋅ 点赞:(0)

        在软件设计中,外观模式(Facade Pattern)和中介模式(Mediator Pattern)是两种常见的行为设计模式,它们都在一定程度上简化了系统间的交互,但具体的应用场景、实现方式和产生的效果却截然不同。本文将详细解析这两种模式的定义、特点、区别,并通过Java语言进行示例演示,帮助读者更好地理解和应用这两种设计模式。

一、外观模式(Facade Pattern)

1. 定义

        外观模式为子系统中的一组接口提供一个一致的界面,定义了一个高层接口,使得这一子系统更加容易使用。它属于对象结构型模式,通过引入一个新的外观角色来降低原有系统的复杂度,同时降低客户类与子系统的耦合度。

2. 特点

  • 又叫做门面模式,是迪米特法则的一种具体实现。
  • 通过引入一个新的外观角色来降低原有系统的复杂度。
  • 所指的子系统是一个广义的概念,它可以是一个类、一个功能模块、系统的一个组成或者一个完整的系统。
  • 为多个业务类的调用提供了一个统一的入口,简化了类与类之间的交互。

3. 示例

        以设计一个保安系统为例,该系统由录像机、电灯、红外线监控和警报器组成。保安系统的操作人员需要经常将这些仪器启动和关闭。如果不使用外观模式,保安类需要用到所有的录像机(Camera)、电灯(Light)、感应器(Sensor)和警报器(Alarm)对象,这会导致代码复杂且难以维护。使用外观模式后,可以大大简化操作。

// 外观角色(Facade)
public class SecurityFacade {
    private Camera camera;
    private Light light;
    private Sensor sensor;
    private Alarm alarm;

    public SecurityFacade() {
        camera = new Camera();
        light = new Light();
        sensor = new Sensor();
        alarm = new Alarm();
    }

    // 提供一键启动所有设备的方法
    public void armSystem() {
        camera.on();
        light.on();
        sensor.on();
        alarm.on();
    }

    // 提供一键关闭所有设备的方法
    public void disarmSystem() {
        camera.off();
        light.off();
        sensor.off();
        alarm.off();
    }

    // 其他操作方法...
}

// 子系统角色(子系统中的具体实现类)
class Camera {
    public void on() {
        System.out.println("Camera is on.");
    }

    public void off() {
        System.out.println("Camera is off.");
    }
}

class Light {
    public void on() {
        System.out.println("Light is on.");
    }

    public void off() {
        System.out.println("Light is off.");
    }
}

class Sensor {
    public void on() {
        System.out.println("Sensor is on.");
    }

    public void off() {
        System.out.println("Sensor is off.");
    }
}

class Alarm {
    public void on() {
        System.out.println("Alarm is on.");
    }

    public void off() {
        System.out.println("Alarm is off.");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        SecurityFacade facade = new SecurityFacade();

        // 启动保安系统
        facade.armSystem();

        // ... 执行其他操作 ...

        // 关闭保安系统
        facade.disarmSystem();
    }
}


        在上面的示例中,SecurityFacade 类作为外观角色,封装了保安系统的所有设备,并提供了一键启动和关闭的方法。客户端代码只需与 SecurityFacade 交互,无需关心具体设备的实现细节,从而大大降低了系统的复杂度和耦合度。

二、中介模式(Mediator Pattern)

1. 定义

        中介模式用一个中介对象来封装一系列对象的交互,使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。它属于行为型模式,通过引入中介者来协调多个对象之间的交互。

2. 特点

  • 有多个系统或者对象发生交互,但又不能直接进行交互。
  • 通过一个中介者来保留所有的交互对象(又叫同事类)的引用。
  • 同事类也需要保留中介者的引用,以便调用中介者中的方法与其他同事类发生交互。
  • 中介者可以根据实际情况,如果系统复杂,有多个中介者,那么可以编写抽象中介者,如果没有则直接编写具体中介者。

3. 示例

        以聊天室系统为例,多个用户需要在一个聊天室内进行交互。如果不使用中介模式,每个用户都需要与其他用户直接建立连接,这会导致系统复杂且难以维护。使用中介模式后,可以引入一个聊天室中介者来协调用户之间的交互。

// 抽象同事类(用户)
abstract class Colleague {
    protected Mediator mediator;

    public abstract void send(String message);

    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }
}

// 具体同事类(用户A)
class UserA extends Colleague {
    public void send(String message) {
        mediator.sendMessage(this, message);
    }

    public void receive(String message) {
        System.out.println("UserA received: " + message);
    }
}

// 具体同事类(用户B)
class UserB extends Colleague {
    public void send(String message) {
        mediator.sendMessage(this, message);
    }

    public void receive(String message) {
        System.out.println("UserB received: " + message);
    }
}

// 抽象中介者
abstract class Mediator {
    public abstract void sendMessage(Colleague colleague, String message);
}

// 具体中介者(聊天室中介者)
class ChatRoom extends Mediator {
    private UserA userA;
    private UserB userB;

    public void setUserA(UserA userA) {
        this.userA = userA;
        userA.setMediator(this);
    }

    public void setUserB(UserB userB) {
        this.userB = userB;
        userB.setMediator(this);
    }

    @Override
    public void sendMessage(Colleague colleague, String message) {
        if (colleague == userA) {
            userB.receive(message);
        } else if (colleague == userB) {
            userA.receive(message);
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        ChatRoom chatRoom = new ChatRoom();

        UserA userA = new UserA();
        UserB userB = new UserB();

        chatRoom.setUserA(userA);
        chatRoom.setUserB(userB);

        // 用户A发送消息
        userA.send("Hello, UserB!");

        // 用户B发送消息
        userB.send("Hi, UserA! How are you?");
    }
}


        在上面的示例中,ChatRoom 类作为中介者,封装了用户A和用户B之间的交互。用户A和用户B只需与 ChatRoom 交互,无需直接建立连接,从而降低了系统的复杂度和耦合度。同时,ChatRoom 类还负责协调用户之间的消息传递,确保消息能够正确地发送给目标用户。

三、外观模式与中介模式的区别

目的不同

  • 外观模式的主要目的是简化子系统的接口,为客户提供一个统一的访问入口,从而降低系统的复杂度和耦合度。
  • 中介模式的主要目的是协调多个对象之间的交互,使它们能够松散耦合地协作,从而降低系统的复杂度和提高可扩展性。

结构不同

  • 外观模式通常只有一个外观类,它封装了子系统的所有接口,并提供了一个高层接口供客户使用。
  • 中介模式通常有一个中介者类和多个同事类,中介者类负责协调同事类之间的交互,同事类则通过中介者类与其他同事类进行通信。

交互方式不同

  • 在外观模式中,客户与外观类进行交互,外观类再与子系统中的具体类进行交互。客户无需关心子系统的具体实现细节。
  • 在中介模式中,同事类通过中介者类进行交互,它们之间不直接建立连接。中介者类负责协调同事类之间的消息传递和协作。

应用场景不同

  • 外观模式适用于需要将复杂子系统简化成一个易于使用的接口的场景,如复杂的图形界面、数据库访问层等。
  • 中介模式适用于需要协调多个对象之间交互的场景,如聊天室系统、交通控制系统等。