【Java】23种设计模式——10.外观模式22.中介者模式15.观察者模式
接下来,我们将介绍三种模式:外观模式、中介者模式、观察模式。
模式
外观模式
外观模式(Facade Pattern) 是一种 结构型设计模式。通过提供统一的 高层接口,隐藏子系统的复杂性,简化客户端与多个子系统之间的交互。其核心是 封装复杂性,提供“一站式”调用入口。
外观模式的核心角色
| 角色 | 职责 | 示例场景 |
|---|---|---|
| Facade(外观类) | 封装子系统的复杂调用逻辑,提供简洁接口 | HomeTheaterFacade(家庭影院控制中心) |
| Subsystems(子系统类) | 实现具体功能,对外观类透明 | 灯光系统、音响系统、投影系统 |
适用场景
- 复杂系统整合 多个子系统需要统一的入口(如电商下单流程)。
- 分层架构设计 提供分层接口隔离底层实现(如框架API)。
- 遗留系统适配 为新系统封装旧接口,减少迁移成本。
使用
设计一个家庭影院控制系统,用户只需要通过一个按钮即可完成“观影模式”(关灯、开投影、开影音)。
-
子类系统 (灯光系统、投影仪系统、影响系统)
/* * 子系统 : 灯光系统 * @Author:lyj * @Date:2025/5/7 16:17 */ public class LightSystem { /** * 灯光调暗至观影模式 */ public void dimLight(){ System.out.println("\uD83D\uDCA1 灯光调暗至观影模式"); } /** * 灯光调亮至正常模式 */ public void brightLight(){ System.out.println("\uD83D\uDCA1 灯光调亮至正常模式"); } public void offLight(){ System.out.println("\uD83D\uDCA1 关闭灯光"); } } /* * 子系统 : 音响系统 * @Author:lyj * @Date:2025/5/7 16:17 */ public class SoudSystem { /** * 启动环绕声模式 */ public void on() { System.out.println("\uD83D\uDD0A 音响系统启动,切换至环绕声模式"); } /** * 设置音量 * @param level */ public void Volume(int level) { System.out.println("\uD83D\uDD0A 音量设置为:" + level); } /** * 关闭音响系统 */ public void off() { System.out.println("\uD83D\uDD0A 音响系统关闭"); } } /** * 子系统 : 设置投影仪 * @Author:lyj * @Date:2025/5/7 16:21 */ public class Projector { /** * 启动投影仪 */ public void start() { System.out.println("\uD83D\uDCFD\uFE0F 投影仪启动,切换到HDMI输入"); } /** * 关闭投影仪 */ public void shutDown() { System.out.println("\uD83D\uDCFD\uFE0F 投影仪关闭"); } } -
外观类 (家庭影院操作)
/** * 外观类 : 家庭影院操作 * @Author:lyj * @Date:2025/5/7 16:24 */ public class HomeTheaterFacade { private LightSystem lightSystem; private SoudSystem soudSystem; private Projector projector; public HomeTheaterFacade(){ lightSystem = new LightSystem(); soudSystem = new SoudSystem(); projector = new Projector(); } /** * 一键开启观影模式 */ public void startMovie(){ lightSystem.dimLight(); soudSystem.on(); projector.start(); } public void endMovie(){ lightSystem.offLight(); soudSystem.off(); projector.shutDown(); } }测试
HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(); homeTheaterFacade.startMovie(); // 开启 System.out.println("----------------------------------------------------------------------------"); homeTheaterFacade.endMovie(); // 关闭运行结果如下:
![image]()
中介者模式
中介者模式:是23种设计模式中的行为模式,旨在通过封装对象间的交互逻辑,降低多个对象间的耦合度。
中介者模式的优势包括:
- 降低耦合度 对象间无需直接引用,通信统一由中介者处理。
- 集中控制交互逻辑 新增同事类时只需要改中介者,避免分散到各对象中 (如添加消息过滤功能)
- 简化多对多关系 将复杂的网状通信变为星型结构(如飞机与塔台管制系统)
中介者模式核心思想
| 角色 | 职责 |
|---|---|
| Mediator(中介者接口) | 定义中介者接口,协调各对象间的通信(如聊天室转发消息) |
| ConcreteMediator(中介者实现类) | 实现具体协调逻辑,管理并维护所有同事对象的引用 |
| Colleague(同事接口类) | 定义同事类接口,每个同事类持有中介者引用,通过中介者与其他同事通信 |
应用场景
- GUI组件交互 窗口中的按钮、输入框等组件通过中介者协调事件(如点击触发输入框刷新)。
- 航空管制系统 飞机与塔台通过中介者交换位置和状态信息,避免飞机间直接通信。
- 游戏引擎角色交互 游戏角色通过中介者处理战斗、交易等交互逻辑。
使用
聊天室消息转发。
- 中介者接口 (聊天室接口类)
/**
* 中介者接口 : 聊天室通用接口
* @Author:lyj
* @Date:2025/5/13 18:07
*/
public interface ChatMediator {
/**
* 发送消息
* @param msg 消息
* @param user 发送用户
*/
public void sendMessage(String msg, User user);
/**
* 添加用户
* @param user 用户
*/
public void addUser(User user);
}
- 中介者实现类
/**
* 具体中介者 : 聊天室
* @Author:lyj
* @Date:2025/5/13 18:11
*/
public class ChatRoomMediator implements ChatMediator {
/**
* 聊天室成员
*/
private List<User> users= new ArrayList<>();
/**
* 发送消息
* @param msg 消息
* @param sender 发送用户
*/
@Override
public void sendMessage(String msg, User sender) {
for (User user : users) {
if (user != sender) { // 消息排除发送者自身
user.receive(msg);
}
}
}
/**
* 添加用户
* @param user 用户
*/
@Override
public void addUser(User user) {
users.add(user);
}
}
- 同事类
/**
* 抽象同事类: 用户
* @Author:lyj
* @Date:2025/5/13 18:10
*/
public abstract class User {
protected ChatMediator mediator; // 聊天室
protected String name; // 用户名
/**
* 构造函数
* @param mediator 聊天室
* @param name 用户名
*/
public User(ChatMediator mediator, String name)
{
this.mediator = mediator;
this.name = name;
}
/**
* 发送消息
* @param msg
*/
public abstract void send(String msg);
/**
* 接收消息
* @param msg 消息
*/
public abstract void receive(String msg);
}
/**
* 具体同事类(普通用户)
* @Author:lyj
* @Date:2025/5/13 18:16
*/
public class ChatUser extends User {
/**
* 构造函数
*
* @param mediator 聊天室
* @param name 用户名
*/
public ChatUser(ChatMediator mediator, String name) {
super(mediator, name);
}
/**
* 发送消息
* @param msg 消息内容
*/
@Override
public void send(String msg) {
System.out.println(this.name + "[发送消息]: =" + msg);
mediator.sendMessage(msg, this); // 通过中介者返送消息
System.out.println("");
}
/**
* 接收消息
* @param msg 消息内容
*/
@Override
public void receive(String msg) {
System.out.println(this.name + "[接收消息]: =" + msg);
}
}
客户端使用:
// 创建中介者(聊天室)
ChatMediator chatRoom = new ChatRoomMediator();
// 创建用户并注册聊天室
ChatUser user1 = new ChatUser(chatRoom, "张三");
ChatUser user2 = new ChatUser(chatRoom, "李四");
ChatUser user3 = new ChatUser(chatRoom, "王五");
chatRoom.addUser(user1);
chatRoom.addUser(user2);
chatRoom.addUser(user3);
// 发送消息
user1.send("你好,我是张三");
user2.send("你好,我是李四");
运行结果:

观察者模式
观察者模式(Observer Pattern) 是 GoF 23 种设计模式中的 行为型模式,用于建立 对象间一对多的依赖关系。当一个对象(被观察者/主题)状态变化时,所有依赖它的对象(观察者)都会收到通知并自动更新。
观察者模式优势:
- 松耦合 被观察者无需了解观察者的具体实现,只需要接口交互(如气象站无需知道显示设备类型)
- 动态订阅机制 可运行时时动态添加/移除观察者(如临时关闭某个显示设备)
- 广播通讯能力 状态变化时自动通知所有观察者(如股票价格变动通知多个交易终端)
角色
| 角色 | 职责 |
|---|---|
| Subject(抽象被观察者) | 被观察者接口,定义注册观察者、删除观察者、通知观察者的方法 |
| ConcreteSubject(具体被观察者) | 具体被观察者,维护观察者列表,在状态变化时触发通知 |
| Observer(抽象观察者) | 观察者接口,定义接收通知后的响应方法(如更新数据) |
| ConcreteObserver(具体观察者) | 具体观察者,实现响应逻辑(如刷新界面显示 |
使用场景
- GUI事件监听 按钮点击事件触发多个监听的
onClick()方法 - 消息队列系统 生产者发布消息,多个消费之订阅并处理消息。
- 游戏引擎 角色血量变化触发UI血条、成就系统的更新。
- 配置中心更新 配置修改后自动同步到所有微信服务模块。
使用
气象站数据更新通知
-
抽象被观察者 (气象站通用接口)
/** * 被观察者接口 * @Author:lyj * @Date:2025/5/14 11:40 */ public interface Subject { /** * 注册观察者 * @param observer 观察者 */ public void registerObserver(Observer observer); /** * 移除观察者 * @param observer 观察者 */ public void removeObserver(Observer observer); /** * 通知观察者 */ public void notifyObservers(); } -
具体被观察者 (气象站)
/** * 被观察者 : 气象站 * @Author:lyj * @Date:2025/5/14 11:51 */ public class WeatherSatation implements Subject { private List<Observer> observers = new ArrayList<>(); private float temperature; /** * 注册观察者 * @param observer 观察者 */ @Override public void registerObserver(Observer observer) { observers.add(observer); } /** * 移除观察者 * @param observer 观察者 */ @Override public void removeObserver(Observer observer) { observers.remove(observer); } /** * 模拟温度变化,并触发通知 */ @Override public void notifyObservers() { for (Observer observer : observers) { observer.update(temperature); } } /** * 模拟温度变化,并触发通知 * @param temperature 温度变化 */ public void setTemperature(float temperature) { this.temperature = temperature; notifyObservers(); System.out.println(); } } -
抽象观察者 (抽象观察者获取气温)
/** * 观察者接口 * @Author:lyj * @Date:2025/5/14 11:48 */ public interface Observer { /** * 更新天气 * @param temperature 气温 */ public void update(float temperature); } -
具体观察者 (设备获取气温)
/**
* 具体观察者 : 显示设备
* @Author:lyj
* @Date:2025/5/14 15:26
*/
public class DisplayDevice implements Observer {
private String deviceName; // 设备名称
public DisplayDevice(String deviceName) {
this.deviceName = deviceName;
}
/**
* 更新数据(接收更新温度通知)
* @param temperature 气温
*/
@Override
public void update(float temperature) {
System.out.printf("[%s]收到通知,温度:%.1f°C\n" ,deviceName, temperature);
}
}
运行客户端:
// 创建被观察者
WeatherSatation weatherSatation = new WeatherSatation();
// 创建观察者
Observer displayDevice1 = new DisplayDevice("手机显示屏");
Observer displayDevice2 = new DisplayDevice("电视显示屏");
// 注册观察者
weatherSatation.registerObserver(displayDevice1);
weatherSatation.registerObserver(displayDevice2);
// 模拟温度变化
weatherSatation.setTemperature(25f);
weatherSatation.setTemperature(30f);
// 移除一个观察者
weatherSatation.removeObserver(displayDevice1);
weatherSatation.setTemperature(27.6f);
运行结果:

扩展——发布订阅者模式
发布订阅模式,是观察者模式的升级版。
观察者模式VS发布订阅者模式,有什么区别和联系呢?
- 观察者模式 :被观察者直接维护观察者列表,强耦合(如气象站直接调用
update()方法) - 发布-订阅者模式 : 通过消息代理(Broker) 解耦,发布者和订阅者互不知晓对方的存在(如 Kafka、MQIT)
关键差异对比
| 特征 | 观察者模式 | 发布-订阅者模式 |
|---|---|---|
| 耦合度 | 被观察者持有观察者引用 | 通过消息代理完全解耦 |
| 通信方式 | 同步调用update()方法 |
异步消息队列(可跨进程/网络) |
| 扩展性 | 适合单机简单场景 | 适合分布式系统(如微服务) |
有志者,事竟成,破釜沉舟,百二秦关终属楚; 苦心人,天不负,卧薪尝胆,三千越甲可吞吴。


浙公网安备 33010602011771号