本文主要是介绍持续总结中!2024年面试必问 20 道设计模式面试题(四),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
上一篇地址:持续总结中!2024年面试必问 20 道设计模式面试题(三)-CSDN博客
七、观察者模式(Observer Pattern)是如何工作的?
观察者模式(Observer Pattern),又称为发布-订阅模式,是一种行为设计模式,它定义了对象间的一种一对多的依赖关系,使得当一个对象状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式通常用于实现分布式事件处理系统。
观察者模式的主要组件:
-
主题(Subject):
- 主题是观察者模式的核心,它维护了一组观察者对象的引用,并提供接口用于注册(attach)、移除(detach)和通知(notify)观察者。
-
观察者(Observer):
- 观察者是一个接口,定义了观察者对象必须实现的更新接口,以便在主题状态改变时得到通知。
-
具体主题(ConcreteSubject):
- 具体主题实现了主题接口,存储状态信息,并提供方法供观察者注册和移除自己。当状态发生改变时,它会自动通知所有注册的观察者。
-
具体观察者(ConcreteObserver):
- 具体观察者实现了观察者接口,根据主题的当前状态更新自己的状态。通常包含一个指向具体主题的引用,但这个引用不是必需的,取决于具体的实现。
-
客户端(Client):
- 客户端代码创建并配置了具体主题和具体观察者,将观察者注册到主题上,并触发事件以演示观察者模式的工作。
观察者模式的工作原理:
-
注册观察者:具体观察者对象通过调用具体主题的注册方法将自己注册为观察者。
-
状态变更:当具体主题的状态发生变化时,它会调用所有注册观察者的更新方法。
-
通知观察者:具体主题通过调用观察者的更新方法来通知它们状态已经改变,通常传递一些必要的信息,如变化的状态本身或一个事件对象。
-
更新状态:具体观察者接收到通知后,根据传递的信息更新自己的状态。
示例代码(Java):
// 观察者接口
interface Observer {void update(String message);
}// 主题接口
interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}// 具体主题
class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();private String state;public void registerObserver(Observer o) {observers.add(o);}public void removeObserver(Observer o) {observers.remove(o);}public void notifyObservers() {for (Observer observer : observers) {observer.update(state);}}public void setState(String state) {this.state = state;notifyObservers();}
}// 具体观察者
class ConcreteObserver implements Observer {private ConcreteSubject subject;public ConcreteObserver(ConcreteSubject subject) {this.subject = subject;subject.registerObserver(this);}@Overridepublic void update(String message) {System.out.println("Received update: " + message);}
}// 客户端代码
public class ObserverPatternDemo {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();new ConcreteObserver(subject); // 注册观察者subject.setState("State 1"); // 状态变更,通知观察者subject.setState("State 2"); // 再次状态变更}
}
在这个示例中,ConcreteSubject
是具体主题,它维护了一个观察者列表,并在状态变化时通知所有观察者。ConcreteObserver
是具体观察者,实现了Observer
接口,并在接收到更新时打印消息。客户端代码创建了主题和观察者,并演示了状态更新和观察者注册的过程。
观察者模式使得对象间的耦合度降低,当一个对象的状态变化时,依赖于它的对象会自动更新,而无需直接调用这些对象的方法。这使得系统更加灵活和易于维护。
八、装饰器模式(Decorator Pattern)和适配器模式有何不同?
装饰器模式(Decorator Pattern)和适配器模式(Adapter Pattern)虽然都是结构型设计模式,但它们解决的问题和设计目的是不同的。以下是两种模式的主要区别:
目的不同:
-
适配器模式 主要用于使不兼容的接口能够一起工作。它通常用于将一个类的接口转换成客户端期望的另一个接口,从而让原本由于接口不兼容而不能一起工作的类可以协同工作。
-
装饰器模式 主要用于动态地给一个对象添加额外的职责。它允许用户在不修改原始对象的基础上,通过添加装饰类来扩展对象的功能。
结构不同:
-
适配器模式 包含以下角色:
- 目标接口(Target):希望适配的接口。
- 适配者(Adaptee):需要适配的类。
- 适配器(Adapter):通过在内部包装一个适配者对象,把源接口转换成目标接口。
-
装饰者模式 包含以下角色:
- 抽象组件(Component):定义了被装饰接口。
- 具体组件(ConcreteComponent):实现了抽象组件的具体类。
- 抽象装饰者(Decorator):抽象类,实现了装饰接口,并持有一个装饰接口的引用。
- 具体装饰者(ConcreteDecorator):实现抽象装饰者,添加额外的职责。
使用场景不同:
-
适配器模式 常用于以下场景:
- 需要将一个已有的类集成到一个新系统中,但接口不兼容。
- 需要复用一些已有的类,但这些类的接口与新系统的接口不一致。
-
装饰者模式 常用于以下场景:
- 需要动态地给对象添加职责,同时希望避免使用继承带来的耦合。
- 需要通过一种灵活的方式来扩展对象的功能,同时保持对象的开放封闭原则。
行为不同:
-
适配器模式 通常只关注于接口的转换,不涉及对象功能的扩展。
-
装饰者模式 允许通过多个装饰者的嵌套使用,来逐步添加多个职责,形成一种链式结构。
示例:
-
适配器模式示例:假设有一个第三方音乐播放器类
ThirdPartyMusicPlayer
,它有一个playMusic()
方法。你的系统需要一个play()
方法的接口。可以创建一个适配器MusicPlayerAdapter
,它实现了play()
方法,内部调用ThirdPartyMusicPlayer
的playMusic()
方法。 -
装饰者模式示例:假设有一个
Coffee
类,有一个cost()
方法返回咖啡的价格。为了添加如加糖、加牛奶等额外服务,可以创建一个装饰者CoffeeDecorator
,它持有一个Coffee
对象的引用,并在调用cost()
方法时添加额外的费用。
总结来说,适配器模式主要用于接口转换,而装饰者模式主要用于对象功能的动态扩展。两者虽然都可以用于复用已有的代码,但它们关注的问题和实现方式是不同的。
这篇关于持续总结中!2024年面试必问 20 道设计模式面试题(四)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!