四十五:策略模式
策略模式属于对象的行为模式,其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响客户端的情况下发生变化.
问题描述:
假设现在要对不同地图书进行打折,如对所有教材类图书实行每本一元的折扣,对连环画图书每本7%的折扣,对非教材类的计算机图书3%的折扣,其余图书没有折扣.这个问题如何解决?
解决方案:
(1)所有的业务逻辑都放在客户端里面,客户端利用条件选择语句决定使用哪一个算法,这样的话客户端代码会变得复杂难以维护.
(2)客户端可以利用继承的办法在子类里面实现不同的行为,但是这样会使得环境和行为紧密耦合在一起,强耦合会使两都不能单独深化
(3)使用策略模式把行为和环境割开来,环境类负责维持和查询行为类,各种算法则在具体的策略类(ConcreteStrategy)中提供,由于算法和环境独立开来,算法的增减,修改都不会影响环境和客户端.
策略模式正是解决这个问题的系统化方法,当出现新的折扣或现有的折扣政策出现变化时,只需要实现新的策略类,并在客户端登记即可,策略模式相当于"可插入式的算法"
一:策略模式的结构
这个模式涉及到三个角色:
(A)环境(Context)角色:持有一个Strategy类的引用.
(B)抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现,此角色给出所有的具体策略类所需要的接口。
(C)具体策略(ConcreteStrategy)角色:包装了相关的算法或行为
下面是示意代码:
package cai.milenfan.basic.test; public class Context { private Strategy strategy; //策略方法 public void contextInterfact(){ strategy.strategyInterface(); } }
package cai.milenfan.basic.test; abstract public class Strategy { //策略方法 public abstract void strategyInterface(); }
package cai.milenfan.basic.test; public class ConcreteStrategy extends Strategy{ //策略方法 public void strategyInterface(){ //write your algorithm code here } }
package cai.milenfan.basic.test; abstract public class DiscountStrategy { abstract public double calculateDiscount(); }
package cai.milenfan.basic.test; public class FlatRateStrategy extends DiscountStrategy{ private double amount; private double price = 0; private int copies = 0; public FlatRateStrategy(double price, int copies) { this.price = price; this.copies = copies; } public double getAmount() { return amount; } public void setAmount(double amount) { this.amount = amount; } public double calculateDiscount() { return copies * amount; } }
package cai.milenfan.basic.test; public class NoDiscountStrategy extends DiscountStrategy{ private double price = 0.0; private int copies = 0; public NoDiscountStrategy(double price, int copies) { this.price = price; this.copies = copies; } public double calculateDiscount() { return 0.0; } }
package cai.milenfan.basic.test; public class PercentageStrategy { private double percent = 0.0; private double price = 0.0; private int copies = 0; public PercentageStrategy(double price, int copies) { this.price = price; this.copies = copies; } public double getPercent() { return percent; } public void setPercent(double percent) { this.percent = percent; } public double calculateDiscount() { return copies * price * percent; } }