Stategy策略模式:定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。策略模式使得算法可以在不影响到客户端的情况下发生变化,它也被成为政策模式,是一种行为型模式。
策略模式的结构:
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。
简单来说就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。
策略模式.png
策略模式包含以下3个角色:
1)Context(环境类):负责使用算法策略,其中维持了一个抽象策略类的引用实例。
2)Strategy(抽象策略类):所有策略类的父类,为所支持的策略算法声明了抽象方法。=> 既可以是抽象类也可以是接口
3)ConcreteStrategy(具体策略类):实现了在抽象策略类中声明的方法。
背景: 假设现在要设计一个卖水果系统,本系统可能对所有的高级会员提供每单20%的促销折扣;对中级会员提供每单10%的促销折扣;对初级会员没有折扣,以后还有可能推出更多类别的优惠折扣,比如说买满多少折扣多少等等等等……
使用策略模式来实现的结构图如下:
水果系统策略模式.png
package Paint;
// 抽象策略(Strategy)角色
public interface MemberStrategy {
/**
* 计算水果价格
* @param booksPrice 原价
* @return 折后价
*/
public double calcPrice(double Price);
}
package Paint;
// ConcreteStrategy(具体策略类)
public class PrimaryMemberStrategy implements MemberStrategy {
@Override
public double calcPrice(double Price) {
System.out.println("对于初级会员的没有折扣");
return Price;
}
}
package Paint;
// ConcreteStrategy(具体策略类)
public class IntermediateMemberStrategy implements MemberStrategy {
@Override
public double calcPrice(double Price) {
System.out.println("对于中级会员的折扣为10%");
return Price * 0.9;
}
}
package Paint;
// ConcreteStrategy(具体策略类)
public class AdvancedMemberStrategy implements MemberStrategy {
@Override
public double calcPrice(double Price) {
System.out.println("对于高级会员的折扣为20%");
return Price * 0.8;
}
}
// 具体策略类--实现了在抽象策略类中声明的方法
package Paint;
public class Price {
// 持有一个具体的策略对象
private MemberStrategy strategy;
/**
* 构造函数,传入一个具体的策略对象
*
* @param strategy
* 具体的策略对象
*/
public Price(MemberStrategy strategy) {
this.strategy = strategy;
}
//计算折后价
public double quote(double Price) {
return this.strategy.calcPrice(Price);
}
}
package Paint;
public class Client {
public static void main(String[] args) {
// 选择并创建需要使用的策略对象
MemberStrategy strategy = new AdvancedMemberStrategy();
// 创建环境
Price price = new Price(strategy);
// 计算价格
double quote = price.quote(300);
System.out.println("最终价格为:" + quote);
}
}
计算结果
策略模式仅仅封装算法,提供新的算法插入到已有系统中,以及老算法从系统中“退休”的方法,策略模式并不决定在何时使用何种算法,在什么情况下使用什么算法是由客户端决定的。
------- 认识策略模式 -------
策略模式的重心——不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。
算法的平等性——各个策略算法的平等性。对于一系列具体的策略算法,大家的地位是完全一样的,正因为这个平等性,才能实现算法之间可以相互替换。所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。所以可以这样描述这一系列策略算法:策略算法是相同行为的不同实现。
运行时策略的唯一性——运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同的策略实现中切换,但是同时只能使用一个。
公有的行为——经常见到的是,所有的具体策略类都有一些公有的行为。这时候,就应当把这些公有的行为放到共同的抽象策略角色Strategy类里面。当然这时候抽象策略角色必须要用Java抽象类实现,而不能使用接口。
这其实也是典型的将代码向继承等级结构的上方集中的标准做法。
示例.png
策略模式的优点
1)提供了对开闭原则的完美支持,用户可以在不修改原有系统的基础上选择具体算法或行为,也可以灵活地增加新的算法或行为。
2)避免了多重的if-else条件选择语句,利于系统的维护。
3)提供了一种算法的复用机制,不同的环境类可以方便地复用这些策略类。
策略模式的缺点
1)客户端需要知道所有的策略类,并自行决定使用哪一个策略 => 只适用于客户端了解所有策略算法的情况。
2)将造成系统产生很多的具体策略类,任何细小的变化都将导致系统要增加一个具体策略类 => 类的个数也许会超出预期。
3)无法在客户端同时使用多个策略类 => 客户端每次只能使用一个策略类。
应用场景
1)如果一个系统要动态地在几种算法之间选择其中一种
2)如果有难以维护的多重if-else条件选择语句是为了实现对象的行为
3)不希望客户知道复杂的与算法有关的数据结构,可以将其封装到策略中 => 提高算法的保密性和安全性!
网友评论