行为型模式(一):模板方法模式、观察者模式
- 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 milk
Boiling 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<>();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public 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;
@Override
public 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% humidity
Current conditions: 82.0F degrees and 70.0% humidity
通过观察者模式,可以实现对象之间的解耦,使得一个对象的变化能够自动通知其他对象,而不需要知道这些对象的具体信息。