【设计模式】行为型模式(一):模板方法模式、观察者模式
行为型模式(一):模板方法模式、观察者模式
- 1.模板方法模式(Template)
- 1.1 主要特点
- 1.2 适用场景
- 1.3 示例
- 1.3.1 抽象类定义模板方法
- 1.3.2 子类实现具体步骤
- 1.3.3 客户端
- 1.3.4 结果输出
- 2.观察者模式(Observer)
- 2.1 主要特点
- 2.2 适用场景
- 2.3 示例
- 2.3.1 观察者
- 2.3.2 主题
- 2.3.3 具体主题
- 2.3.4 具体观察者
- 2.3.5 客户端
- 2.3.6 结果输出
1.模板方法模式(Template)
模板方法模式(Template Method
)是一种行为设计模式,它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些特定步骤。
1.1 主要特点
- 定义算法框架:父类定义了执行某个操作的框架,但具体的实现细节留给子类完成。
- 防止子类修改:模板方法在父类中定义为
final
,防止子类修改算法的总体结构。 - 钩子方法:父类可以定义一些 钩子 方法,子类可以选择性地实现这些方法,以影响算法的行为。
1.2 适用场景
- 当你有一个算法的多个变体,但它们的某些步骤是相同的,可以将这些相同的步骤提取到父类中。
- 当你希望子类能够扩展某个算法的某些特定步骤,但不能改变算法的整体结构。
1.3 示例
假设你有一个制作咖啡和茶的过程,它们的步骤大致相同,但某些细节不同。
1.3.1 抽象类定义模板方法
// 抽象类定义了模板方法
abstract class Beverage {// 模板方法,定义了算法的框架final void prepareBeverage() {boilWater();brew();pourInCup();addCondiments();}// 具体步骤,由子类实现abstract void brew();abstract void addCondiments();// 具体步骤,已经在父类中实现void boilWater() {System.out.println("Boiling water");}void pourInCup() {System.out.println("Pouring into cup");}
}
1.3.2 子类实现具体步骤
// 子类实现具体的步骤
class Coffee extends Beverage {void brew() {System.out.println("Dripping coffee through filter");}void addCondiments() {System.out.println("Adding sugar and milk");}
}class Tea extends Beverage {void brew() {System.out.println("Steeping the tea");}void addCondiments() {System.out.println("Adding lemon");}
}
1.3.3 客户端
// 客户端代码
public class TemplateMethodDemo {public static void main(String[] args) {Beverage coffee = new Coffee();coffee.prepareBeverage();System.out.println();Beverage tea = new Tea();tea.prepareBeverage();}
}
1.3.4 结果输出
Boiling water
Dripping coffee through filter
Pouring into cup
Adding sugar and milkBoiling water
Steeping the tea
Pouring into cup
Adding lemon
在这个例子中,Beverage
类定义了制作饮料的模板方法 prepareBeverage
,具体的步骤 brew
和 addCondiments
由子类 Coffee
和 Tea
实现。这样,子类可以在不改变整体算法结构的情况下,实现具体的细节。
2.观察者模式(Observer)
观察者模式(Observer
)是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象(称为 主题 或 发布者)的状态发生变化时,所有依赖于它的对象(称为 观察者 或 订阅者)都会自动得到通知并更新。
2.1 主要特点
- 主题(
Subject
):维护一个观察者列表,并提供添加、删除和通知观察者的方法。 - 观察者(
Observer
):定义一个更新接口,当主题状态发生变化时,观察者会收到通知并更新自己的状态。 - 具体主题(
Concrete Subject
):实现主题接口,当状态发生变化时,通知所有观察者。 - 具体观察者(
Concrete Observer
):实现观察者接口,根据主题的状态变化更新自己的状态。
2.2 适用场景
- 当一个对象的改变需要同时改变其他多个对象时,可以使用观察者模式。
- 当一个对象需要与多个其他对象保持一致,但又不想直接依赖这些对象时,可以使用观察者模式。
2.3 示例
假设你有一个天气站,当天气变化时,需要通知多个显示设备(如温度显示器、湿度显示器等)更新显示。
2.3.1 观察者
// 观察者接口
interface Observer {void update(float temperature, float humidity, float pressure);
}
2.3.2 主题
// 主题接口
interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}
2.3.3 具体主题
// 具体主题
class WeatherData implements Subject {private List<Observer> observers;private float temperature;private float humidity;private float pressure;public WeatherData() {observers = new ArrayList<>();}@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(temperature, humidity, pressure);}}public void setMeasurements(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;measurementsChanged();}private void measurementsChanged() {notifyObservers();}
}
2.3.4 具体观察者
// 具体观察者
class CurrentConditionsDisplay implements Observer {private float temperature;private float humidity;@Overridepublic void update(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;display();}public void display() {System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");}
}
2.3.5 客户端
// 客户端代码
public class ObserverPatternDemo {public static void main(String[] args) {WeatherData weatherData = new WeatherData();CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay();weatherData.registerObserver(currentConditionsDisplay);weatherData.setMeasurements(80, 65, 30.4f);System.out.println();weatherData.setMeasurements(82, 70, 29.2f);}
}
WeatherData
是主题,维护了一个观察者列表,并提供注册、移除和通知观察者的方法。CurrentConditionsDisplay
是观察者,实现了Observer
接口,当天气数据变化时,会收到通知并更新显示。- 天气站
WeatherData
注册了一个观察者CurrentConditionsDisplay
,当天气数据变化时,观察者会自动更新显示。
2.3.6 结果输出
Current conditions: 80.0F degrees and 65.0% humidityCurrent conditions: 82.0F degrees and 70.0% humidity
通过观察者模式,可以实现对象之间的解耦,使得一个对象的变化能够自动通知其他对象,而不需要知道这些对象的具体信息。