策略模式是一种行为设计模式,它定义了一系列算法,并将每一个算法封装起来,让它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。
策略模式的简单实现通常涉及以下几个部分:定义一个策略接口,然后根据不同的算法实现该接口,最后在一个上下文类中使用这些策略。以下是一个简化的示例:
(1)策略接口
策略接口定义了一个方法,所有的具体策略类都需要实现这个方法。
public interface Strategy {
int execute(int a, int b);
}
(2)具体策略类
我们实现不同的策略类来执行不同的算法。比如,加法
、减法
、乘法
。
// 加法策略
public class AddStrategy implements Strategy {
@Override
public int execute(int a, int b) {
return a + b;
}
}
// 减法策略
public class SubtractStrategy implements Strategy {
@Override
public int execute(int a, int b) {
return a - b;
}
}
// 乘法策略
public class MultiplyStrategy implements Strategy {
@Override
public int execute(int a, int b) {
return a * b;
}
}
(3)上下文类
上下文类 Context
使用策略接口来调用具体的策略类。
public class Context {
private Strategy strategy;
// 设置策略
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
// 执行策略
public int executeStrategy(int a, int b) {
return strategy.execute(a, b);
}
}
(4)测试类
在测试类中,我们可以通过设置不同的策略来运行不同的算法。
public class StrategyPatternExample {
public static void main(String[] args) {
Context context = new Context();
// 使用加法策略
context.setStrategy(new AddStrategy());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
// 使用减法策略
context.setStrategy(new SubtractStrategy());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
// 使用乘法策略
context.setStrategy(new MultiplyStrategy());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
(5)输出
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
使用场景:
优点:
缺点:
模版方法模式是一种行为设计模式,它定义了一个操作中的算法骨架,并允许子类在不改变算法结构的情况下,重新定义算法的某些步骤。该模式通过继承实现,父类负责封装大致流程,而具体细节则由子类提供。
假设我们有一个抽象的制作咖啡和茶的流程。虽然制作的步骤相似(比如加热水、倒水等),但是具体的饮料制作细节有所不同(如茶需要浸泡,而咖啡需要过滤)。
(1)抽象类
public abstract class Beverage {
// 模版方法,定义了制作饮料的骨架
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
}
// 固定步骤:烧水
private void boilWater() {
System.out.println("Boiling water");
}
// 固定步骤:倒入杯中
private void pourInCup() {
System.out.println("Pouring into cup");
}
// 变动步骤:由子类实现
protected abstract void brew(); // 不同饮料的冲泡方式不同
// 变动步骤:由子类实现
protected abstract void addCondiments(); // 不同饮料的调料不同
}
(2)具体类:咖啡
public class Coffee extends Beverage {
@Override
protected void brew() {
System.out.println("Brewing coffee");
}
@Override
protected void addCondiments() {
System.out.println("Adding sugar and milk");
}
}
(3)具体类:茶
public class Tea extends Beverage {
@Override
protected void brew() {
System.out.println("Steeping the tea");
}
@Override
protected void addCondiments() {
System.out.println("Adding lemon");
}
}
(4)客户端代码
public class TemplateMethodExample {
public static void main(String[] args) {
Beverage coffee = new Coffee();
Beverage tea = new Tea();
System.out.println("Making coffee:");
coffee.prepareRecipe(); // 按照模板做咖啡
System.out.println("\nMaking tea:");
tea.prepareRecipe(); // 按照模板做茶
}
}
(5)输出
Making coffee:
Boiling water
Brewing coffee
Pouring into cup
Adding sugar and milk
Making tea:
Boiling water
Steeping the tea
Pouring into cup
Adding lemon
使用场景:
多个子类有共有的方法,并且逻辑基本相同时
面对重要、复杂的算法,可以把核心算法设计为模板方法,周边相关细节功能则由各个子类实现。
需要通过子类来决定父类算法中的某个步骤是否执行,实现子类对父类的反向控制。
优点:
缺点:
观察者模式是一种行为设计模式,用于定义对象之间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会自动得到通知并更新。这个模式通常用于事件驱动的系统中。
假设有一个天气预报系统,天气变化时,多个设备(如温度显示、气象站等)需要接收到天气变化的通知。
(1)主题(被观察者)接口
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
(2)观察者接口
public interface Observer {
void update(float temperature, float humidity, float pressure);
}
(3)具体主题(天气数据)
public 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;
notifyObservers(); // 数据更新后通知所有观察者
}
}
(4)具体观察者(温度显示)
public class TemperatureDisplay implements Observer {
private float temperature;
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
display();
}
public void display() {
System.out.println("Temperature Display: " + temperature + "°C");
}
}
(5)具体观察者(气象站)
public class WeatherStation implements Observer {
private float temperature;
private float humidity;
private float pressure;
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
public void display() {
System.out.println("Weather Station - Temperature: " + temperature + "°C, Humidity: " + humidity + "%, Pressure: " + pressure + "hPa");
}
}
(6)客户端代码(测试)
public class ObserverPatternExample {
public static void main(String[] args) {
// 创建主题对象
WeatherData weatherData = new WeatherData();
// 创建观察者对象
TemperatureDisplay tempDisplay = new TemperatureDisplay();
WeatherStation weatherStation = new WeatherStation();
// 注册观察者
weatherData.registerObserver(tempDisplay);
weatherData.registerObserver(weatherStation);
// 更新天气数据并通知所有观察者
weatherData.setMeasurements(25.5f, 65.0f, 1013.1f);
weatherData.setMeasurements(27.0f, 60.0f, 1012.5f);
}
}
(7)输出
Temperature Display: 25.5°C
Weather Station - Temperature: 25.5°C, Humidity: 65.0%, Pressure: 1013.1hPa
Temperature Display: 27.0°C
Weather Station - Temperature: 27.0°C, Humidity: 60.0%, Pressure: 1012.5hPa
已经到底啦!!