文章目录
在Java中,策略模式
和模板方法
模式是两种常用的行为型设计模式,它们分别通过不同的方式实现算法的灵活性和代码复用。
以下是结合具体案例的解释和对比:
1. 策略模式(Strategy Pattern)
核心思想:将算法族封装为独立的类,通过组合的方式动态切换算法,使算法的变化独立于客户端。
适用场景:需要在运行时选择不同算法(如支付方式、打折策略、消息发送方式等)的场景。
案例:支付方式选择
代码实现:
// 策略接口(网页2参考)
public interface PaymentStrategy {
void pay(int amount);
}
// 具体策略类
public class CreditCardStrategy implements PaymentStrategy {
@Override
public void pay(int amount) {
System.out.println("信用卡支付:" + amount + "元");
}
}
public class AlipayStrategy implements PaymentStrategy {
@Override
public void pay(int amount) {
System.out.println("支付宝支付:" + amount + "元");
}
}
// 上下文类(环境类)
public class ShoppingCart {
private PaymentStrategy strategy;
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void checkout(int amount) {
strategy.pay(amount);
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
cart.setStrategy(new CreditCardStrategy());
cart.checkout(100); // 输出:信用卡支付:100元
cart.setStrategy(new AlipayStrategy());
cart.checkout(200); // 输出:支付宝支付:200元
}
}
关键点:
• 通过接口定义算法族(如支付方式),具体策略类实现接口。
• 上下文类(如购物车)持有策略接口的引用,客户端动态切换策略。
• 优点:避免多重条件判断,算法可扩展性强。
2. 模板方法模式(Template Method Pattern)
核心思想:定义一个算法的骨架(固定步骤),将某些步骤延迟到子类实现,保证整体流程不变。
适用场景:算法步骤固定但部分实现可能变化(如制作饮料、数据加密流程等)。
案例:制作饮料流程
代码实现:
// 抽象类(网页7参考)
public abstract class Beverage {
// 模板方法(固定步骤)
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
}
// 具体步骤(子类共享)
private void boilWater() {
System.out.println("烧水");
}
// 抽象方法(子类实现)
protected abstract void brew();
protected abstract void addCondiments();
// 钩子方法(可选重写)
protected void pourInCup() {
System.out.println("倒入杯中");
}
}
// 具体子类
public class Tea extends Beverage {
@Override
protected void brew() {
System.out.println("冲泡茶叶");
}
@Override
protected void addCondiments() {
System.out.println("加柠檬");
}
}
public class Coffee extends Beverage {
@Override
protected void brew() {
System.out.println("冲泡咖啡粉");
}
@Override
protected void addCondiments() {
System.out.println("加糖和牛奶");
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
Beverage tea = new Tea();
tea.prepareRecipe(); // 执行烧水→冲泡茶叶→倒入杯中→加柠檬
Beverage coffee = new Coffee();
coffee.prepareRecipe(); // 执行烧水→冲泡咖啡粉→倒入杯中→加糖和牛奶
}
}
关键点:
• 抽象类定义模板方法(如prepareRecipe()
),包含固定步骤和可扩展步骤(如brew()
)。
• 子类仅需实现抽象方法,无法修改算法骨架。
• 优点:代码复用性高,维护流程一致性。
3. 策略模式 vs 模板方法模式
对比维度 | 策略模式 | 模板方法模式 |
---|---|---|
核心机制 | 组合(通过接口动态切换算法) | 继承(父类定义骨架,子类实现细节) |
灵活性 | 更高(运行时动态切换策略) | 较低(编译时确定子类实现) |
代码复用 | 较少(每个策略独立) | 较高(复用父类模板方法) |
适用场景 | 需要多种算法灵活替换(如支付方式) | 固定流程但部分步骤可变(如制作饮料) |
设计原则 | 开闭原则(扩展新策略不修改原有代码) | 好莱坞原则(父类调用子类,而非反向) |
4.总结
• 策略模式更适用于算法频繁变化的场景,例如支付方式、消息发送(如短信/邮件)。
• 模板方法模式适合固定流程但部分步骤需定制化的场景,例如饮品制作、数据处理的标准化流程。
• 选择依据:若需运行时动态切换行为,选策略模式;若需复用固定流程并允许子类扩展细节,选模板方法模式。