策略模式

来源:互联网 发布:淘宝关键词修改不见 编辑:程序博客网 时间:2024/05/01 22:37

策略模式的使用情景:

有一系列平行的解决某一问题的算法,为这些算法抽象出一个接口,所有算法都是该接口的具体实现。实现一个上下文(Context),在上下文中有算法接口的引用。使用算法的客户不直接使用具体算法类,而是和上下文交互,这样实现了客户端和算法的解耦。


假设现在有这样的需求:商家对新客户的报价是原价,老客户打9折,大客户打8.5折。简单的实现可以用多个 if else 判断,但当增加新的定价方案时不容易扩展,需要修改现有代码。这种情况下,使用策略模式较合适。


示例代码

public class Strategy_Model {public static void main(String[] args) {NewCustomerStrategy ns = new NewCustomerStrategy();Price p = new Price(ns);p.quote(100);OldCustomerStrategy os = new OldCustomerStrategy();Price p2 = new Price(os);p2.quote(100);BigCustomerStrategy bs = new BigCustomerStrategy();Price p3 = new Price(bs);p3.quote(100);}}class Price {private Strategy strategy;public Price(Strategy strategy){this.strategy = strategy;}public void quote(double goodPrice){this.strategy.calculatePrice(goodPrice);}}interface Strategy{public void calculatePrice(double goodPrice);}class NewCustomerStrategy implements Strategy{@Overridepublic void calculatePrice(double goodPrice) {// TODO Auto-generated method stubSystem.out.println("新客户原价");}}class OldCustomerStrategy implements Strategy{@Overridepublic void calculatePrice(double goodPrice) {// TODO Auto-generated method stubSystem.out.println("老客户9折 "+goodPrice*0.9);}}class BigCustomerStrategy implements Strategy{@Overridepublic void calculatePrice(double goodPrice) {// TODO Auto-generated method stubSystem.out.println("大客户8.5折 "+goodPrice*0.85);}}

策略模式将具体的算法从业务中独立出来,形成一系列单独的算法类,算法类间可以替换,策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,可维护可扩展。


具体策略的选择,选择权在客户端。上下文(比如上例中的Price类)是客户端和具体策略间的媒介。


策略的实现,一般就像上例抽象一个策略的接口,然后实现不同的策略实现类。如果有公共功能需要实现,那就把接口改成抽象类,公共功能在抽象类中实现。


Strategy 和 Context 的关系:Context中有Strategy的引用,Strategy也可以从Context中获取数据,将Context对象作为参数传递给Strategy,Strategy回调Context的方法获取数据,这种情况下,Context可以作为Strategy的公共功能的实现类。


假设现在有这样的需求:有不同的工资结算方式,比如,美元,人民币,银行转账。下面用策略模式,将上下文对象传递给策略实现对象的方式实现。


示例代码:

public class Strategy_Salary_Model {public static void main(String[] args) {SalaryStrategy rmb = new RMBStrategy();Salary s1 = new Salary("小张", 12000, rmb);s1.paySalary();SalaryStrategy dollar = new DollarStrtegy();Salary s2 = new Salary("Jim", 8000, dollar);s2.paySalary();}}interface SalaryStrategy{public void pay(Salary s);}class Salary{private SalaryStrategy strategy;private double salary;private String userName;public SalaryStrategy getStrategy() {return strategy;}public double getSalary() {return salary;}public String getUserName() {return userName;}public Salary(String userName,double salary,SalaryStrategy strategy){this.userName = userName;this.salary = salary;this.strategy = strategy;}public void paySalary(){this.strategy.pay(this);}}class RMBStrategy implements SalaryStrategy{@Overridepublic void pay(Salary s) {// TODO Auto-generated method stubSystem.out.println("付给 "+s.getUserName()+" RMB "+s.getSalary());}}class DollarStrtegy implements SalaryStrategy{@Overridepublic void pay(Salary s) {// TODO Auto-generated method stubSystem.out.println("付给 "+s.getUserName()+" Dollar "+s.getSalary());}}

结果:

付给 小张 RMB 12000.0付给 Jim Dollar 8000.0

假设现在要扩展一张支付方式:银行转账。因为需要银行账号,故重写一个上下文SalaryBank继承Salary.添加一个新的银行转账的策略。

class SallaryBank extends Salary{private int account;public int getAccount() {return account;}public SallaryBank(String userName, double salary,int bankAccount, SalaryStrategy strategy) {super(userName, salary, strategy);this.account = bankAccount;}}

class BankStrtegy implements SalaryStrategy{@Overridepublic void pay(Salary s) {// TODO Auto-generated method stubSystem.out.println("付给 "+s.getUserName()+" "+s.getSalary()+",通过银行转账,账户:"+((SallaryBank)s).getAccount());}}

public class Strategy_Salary_Model {public static void main(String[] args) {SalaryStrategy rmb = new RMBStrategy();Salary s1 = new Salary("小张", 12000, rmb);s1.paySalary();SalaryStrategy dollar = new DollarStrtegy();Salary s2 = new Salary("Jim", 8000, dollar);s2.paySalary();SalaryStrategy bank = new BankStrtegy();SallaryBank s3 = new SallaryBank("王经理", 8000, 123456,bank);s3.paySalary();}}

结果:

付给 小张 RMB 12000.0付给 Jim Dollar 8000.0付给 王经理 8000.0,通过银行转账,账户:123456

上面的例子通过改变上下文,通过上下文来获取数据。还可以直接修改策略,通过具体策略实现类的构造函数传参。

class BankStrategy2 implements SalaryStrategy{private int account;public BankStrategy2(int account){this.account = account;}@Overridepublic void pay(Salary s) {// TODO Auto-generated method stubSystem.out.println("付给 "+s.getUserName()+" "+s.getSalary()+",通过银行转账,账户:"+this.account);}}


SalaryStrategy bank = new BankStrategy2(789456);Salary s3 = new Salary("王经理", 10000,bank);s3.paySalary();

运行结果:

付给 王经理 10000.0,通过银行转账,账户:789456

两种方式,看情况选用。


对应策略算法在实现上有公共功能的情况,实现方式有:

1),将接口写成抽象类,把公共功能在抽象类中实现。

2),将公共功能放在Context里实现,具体策略对象回调上下文对象。

3),为所有策略算法抽象一个父类,该父类去实现策略接口,在该父类中实现公共功能。


策略模式的本质“分离算法,选择实现” 。




0 0
原创粉丝点击