设计模式 - 策略模式
一、引入
策略模式就像是一个智能的开关,可以根据不同的情况选择不同的策略来解决问题。
比如说你要出门,你可以根据天气情况选择不同的交通工具:如果是晴天,你可以选择骑自行车;如果是雨天,你可以选择坐公交车或打车。这里,根据天气情况选择交通工具就是一种策略。
在程序里,策略模式也类似,它允许你根据不同的情况选择不同的算法或处理方式。比如,对于排序算法,你可以选择使用快速排序、冒泡排序等不同的策略,而不需要改变原有的代码。
策略模式的优点在于它可以让代码更加灵活和可扩展。你可以随时添加新的策略,而不需要改变原来的代码逻辑。同时,策略模式也使得代码更容易理解和维护,因为不同的策略分开了,不会相互干扰。
简单来说,策略模式就是允许你根据不同情况选择不同的方法来解决问题,让程序更灵活、可扩展、易维护。
二、概念
策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,将每个算法封装起来,并使它们可以互相替换,从而使算法的变化独立于使用它们的客户端。
三、基本结构
- 策略接口(Strategy Interface):定义了所有支持的算法的通用接口。通常包括一个或多个方法,用于执行具体的算法。
- 具体策略(Concrete Strategy):实现了策略接口的具体算法。每个具体策略类都实现了一种算法。
- 上下文(Context):维护一个对策略接口的引用,并可以在运行时切换算法。通常会在构造函数中接收一个具体的策略对象。
四、示例代码
/**
* 策略接口
*/
public interface PaymentStrategy {
void pay(int amout);
}
/**
* 支付宝支付
*/
public class PayPalPayment implements PaymentStrategy {
@Override
public void pay(int amout) {
System.out.println("Paid " + amout + " using PayPal.");
}
}
/**
* 信用卡支付
*/
public class CreditCardPayment implements PaymentStrategy {
@Override
public void pay(int amout) {
System.out.println("Paid " + amout + " using credit card.");
}
}
/**
* 上下文 : 维护一个对策略接口的引用,并可以在运行时切换算法。通常会在构造函数中接收一个具体的策略对象。
*/
public class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void checkout(int amout) {
paymentStrategy.pay(amout);
}
}
//客户端
public class Client {
public static void main(String[] args) {
ShoppingCart shoppingCart = new ShoppingCart();
shoppingCart.setPaymentStrategy(new CreditCardPayment());
shoppingCart.checkout(100);
shoppingCart.setPaymentStrategy(new PayPalPayment());
shoppingCart.checkout(200);
}
}
五、用途
在实际开发中,策略模式常常用于以下情况:
- 算法的选择需要在运行时动态确定: 当需要根据不同的条件或用户输入来动态选择不同的算法时,策略模式非常有用。例如,一个电商网站根据用户的会员等级提供不同的折扣策略。
- 减少大型 if-else 或 switch-case 结构: 使用策略模式可以减少代码中的条件判断语句,使代码更清晰、简洁。
- 将算法的实现与使用解耦: 策略模式将算法的实现从使用算法的客户端代码中分离出来,使得算法的变化不会影响到客户端的代码,实现了解耦。
- 实现单一职责原则: 每个策略类只负责实现一种算法,符合单一职责原则,代码更清晰、易维护。
- 可以方便地扩展新的算法: 可以随时新增、修改、删除策略类,而不会影响到其他算法的使用。
地方采用策略模式的例子包括:
- 支付系统: 不同的支付方式(如支付宝、微信、银行卡)可以视作不同的支付策略,根据用户的选择来调用不同的支付策略。
- 排序算法: 不同的排序算法(如快速排序、冒泡排序)可以视作不同的排序策略,可以根据数据规模或其他条件来选择不同的排序策略。
- 电商优惠活动: 根据不同的促销活动(如满减、打折、赠品),选择不同的优惠策略。
- 游戏角色的攻击方式: 不同的角色(如战士、法师、弓手)可以有不同的攻击策略,可以根据角色的选择来调用相应的攻击策略。
总的来说,策略模式在需要动态选择、扩展或替换算法时非常有用,可以使程序更灵活、可扩展、易维护。
六、总结
优点:
- 灵活性高: 策略模式允许在运行时动态选择算法,从而可以根据不同的情况选择不同的策略,使得系统更加灵活。
- 扩展性好: 新的算法可以通过实现新的策略类来添加到系统中,无需修改原有的代码,符合开闭原则。
- 避免使用多重条件判断: 使用策略模式可以避免使用大量的 if-else 或 switch-case 结构,使代码更清晰、简洁。
- 单一职责原则: 每个具体策略类只负责实现一种算法,符合单一职责原则,使代码更清晰、易维护。
缺点:
- 增加了类的数量: 策略模式会增加许多策略类或者具体算法类,可能会导致类的数量增多。
- 客户端必须知道所有的策略类: 客户端必须知道所有的策略类,并在使用时选择合适的策略,这需要一定的了解和判断能力。
- 上下文类中会持有所有的策略对象: 在某些情况下,上下文类可能会持有所有可能用到的策略对象,可能会增加内存开销。
总的来说,策略模式在需要动态选择、扩展或替换算法时非常有用,可以使程序更灵活、可扩展、易维护。然而,也需要根据具体的应用场景来选择是否使用策略模式。