策略模式

来源:互联网 发布:大数据研究所 编辑:程序博客网 时间:2024/06/04 23:19
策略模式(Strategy Pattern)是相对比较简单的一种设计模式,是通过定义一组算法,并且将每个算法封装到具有共同接口的独立类中,从而使它们之间可以相互转换,使算法在不影响客户端的情况下发生变化。

策略模式体现了这样两个原则——封装变化对接口编程而不是对实现编程设计模式的作者把策略模式定义如下:

Define a family of algorithms, encapsulate each one, and make them interchangeable. [The] Strategy [pattern] lets the algorithm vary independently from clients that use it.(策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而变化。)

策略模式将整个软件构建为可互换部分的松耦合的集合,而不是单一的紧耦合系统。松耦合的软件可扩展性更好,更易于维护且重用性好。


策略模式的UML


策略模式共涉及3种角色:
环境角色(Context):也叫上下文角色,用于屏蔽高层模块对策略、算法的直接访问,它持有一个Strategy类的引用。
抽象策略角色(Strategy):对策略、算法进行抽象,是每个具体策略角色必须实现的。
具体策略角色(Concrete Strategy):用于实现具体的策略、算法。

策略模式的应用
以商场促销为例,有的商品是打折促销,有的商品是满减,还有的是不促销的,可以用策略模式进行优惠算法的封装。


抽象策略角色:
public abstract class StrategyDiscount {private int num;private int price;public StrategyDiscount(int price, int num) {this.num = num;this.price = price;}public int getNum() {return num;}public int getPrice() {return price;}public abstract double getDiscount();}

三个具体实现的策略角色,分别代表无促销、满减促销、打折促销
public class NoDiscountStrategy extends StrategyDiscount {public NoDiscountStrategy(int price,int num) {super(num, price);}@Overridepublic double getDiscount() {return getPrice() * getNum();}}

public class FixDiscountStrategy extends StrategyDiscount {public FixDiscountStrategy(int price, int num ) {super(num, price);}@Overridepublic double getDiscount() {int sum = getNum() * getPrice();if(sum > 100 ) {  //满100减20return sum-20;}else return sum;}}

public class PercentDisCountStrategy extends StrategyDiscount {public PercentDisCountStrategy(int price, int num) {super(num, price);}@Overridepublic double getDiscount() {return 0.8 * getPrice() * getNum(); //打八折}}

环境角色Context,屏蔽对具体策略角色的直接访问
public class Context {private StrategyDiscount strategyDiscount;public Context(StrategyDiscount strategyDiscount) {this.strategyDiscount = strategyDiscount;}public double contextCalDisc() {return strategyDiscount.getDiscount();}}

以上关于促销案例的策略模式就已经完成,以下是客户端调用的类
public class Client {public static void main(String[] args) {Context c1 = new Context(new NoDiscountStrategy(20, 6));System.out.println("该商品不促销,购买总额: " + c1.contextCalDisc());Context c2 = new Context(new FixDiscountStrategy(20, 6));System.out.println("该商品参与满减促销,购买总额 : " + c2.contextCalDisc());Context c3 = new Context(new PercentDisCountStrategy(20, 6));System.out.println("该商品参与打八折促销,购买总额 :" + c3.contextCalDisc());}}


以上总结策略模式的优点:
1. 策略模式提供了管理相关算法族的办法,可以把公用的特性移动到抽象策略角色中,以提高重用性。
2. 策略模式提供了可以替换继承关系的办法。继承也可以处理多种算法行为,如果不使用策略模式,那么使用算法或行为的环境类就可能有一些子类,每个子类提供一个不同的算法,这样的话,算法或行为的使用者就    和算法本身混在一起,从而不可能在独立的演化。
3. 使用策略可以避免多重条件转移语句。

策略模式的一些缺点:
1. 客户端必须知道所有的具体策略模式,并自行决定调用哪一个,这对拥有大量策略的应用是困难的。
2. 策略模式会造成很多策略类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样的策略类实例可以被不同的客户端使用。一颗使用享元模式来减少对象的数量。

使用策略模式的场景:
1. 多个类只是在算法或行为上稍有不同的场景。
2. 算法需要自由切换的场景。
3. 需要屏蔽算法规则的场景。



0 0
原创粉丝点击