您的位置:首页 > 其它

设计模式学习笔记之策略模式

2016-05-15 11:13 453 查看
策略模式
定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
说明
1、可以动态地改变对象的行为;
2、各个策略算法的平等性,各个策略算法在实现上是相互独立的,相互之间没有任何依赖的(由此,策略模式也可以描述为“策略算法是相同行为的不同实现”);
3、在运行期间,策略模式在某一时刻,只能使用一个具体的策略算法实现对象,虽然可以动态改变对象行为,但同时只能使用一个;
4、策略模式可以很简单的扩展新的实现算法。方法:先写一个策略算法来实现新的需求,然后在客户端使用时指定该实现算法即可;
5、多个if-elseif语句表达的就是一个平等的功能结构,你要么执行if,要不你就执行else,或者是elseif,这个时候,if块里面的实现和else块里面的实现从运行地位上来讲就是平等的。而策略模式就是把各个平等的具体实现封装到单独的策略实现类了,然后通过上下文来与具体的策略类进行交互。因此多个if-else语句可以考虑使用策略模式。

场景:
1、报价管理系统中,对于销售部门的人来说,要对不同的客户报不同的价格。如:对于普通用户或者新用户来说,报全价;对老客户报的价格,统一折扣5%;大客户报的价格,统一折扣10%。
实现:
A:定义策略接口

/**

* 策略,定义计算报价算法的接口

*/

public interface Strategy {

/**

* 计算应报的价格

* @param goodsPrice 商品销售原价

* @return 计算出来的,应该给客户报的价格

*/

public double calcPrice(double goodsPrice);

}

B:具体实现各个报价标准

/**

* 具体算法实现,为新客户或者是普通客户计算应报的价格

*/

public class NormalCustomerStrategy implements Strategy{

public double calcPrice(double goodsPrice) {

System.out.println("对于新客户或者是普通客户,没有折扣");

return goodsPrice;

}

}

/**

* 具体算法实现,为老客户计算应报的价格

*/

public class OldCustomerStrategy implements Strategy{

public double calcPrice(double goodsPrice) {

System.out.println("对于老客户,统一折扣5%");

return goodsPrice*(1-0.05);

}

}

/**

* 具体算法实现,为大客户计算应报的价格

*/

public class LargeCustomerStrategy implements Strategy{

public double calcPrice(double goodsPrice) {

System.out.println("对于大客户,统一折扣10%");

return goodsPrice*(1-0.1);

}

}

C:价格类,上下文的实现

/**

* 价格管理,主要完成计算向客户所报价格的功能

*/

public class Price {

/**

* 持有一个具体的策略对象

*/

private Strategy strategy = null;

/**

* 构造方法,传入一个具体的策略对象

* @param aStrategy 具体的策略对象

*/

public Price(Strategy aStrategy){

this.strategy = aStrategy;

}

/**

* 报价,计算对客户的报价

* @param goodsPrice 商品销售原价

* @return 计算出来的,应该给客户报的价格

*/

public double quote(double goodsPrice){

return this.strategy.calcPrice(goodsPrice);

}

}

D:写个客户端进行测试

public class Client {

public static void main(String[] args) {

//1:选择并创建需要使用的策略对象

Strategy strategy = new LargeCustomerStrategy ();

//2:创建上下文

Price ctx = new Price(strategy);

//3:计算报价

double quote = ctx.quote(1000);

System.out.println("向客户报价:"+quote);

}

}

2、容错恢复机制。程序运行的时候,正常情况下应该按照某种方式来做,如果按照某种方式来做发生错误的话,系统并不会崩溃,也不会就此不能继续向下运行了,而是有容忍出错的能力,不但能容忍程序运行出现错误,还提供出现错误后的备用方案,也就是恢复机制,来代替正常执行的功能,使程序继续向下运行。
比如在一个系统中,所有对系统的操作都要有日志记录,而且这个日志还需要有管理界面,这种情况下通常会把日志记录在数据库里面,方便后续的管理,但是在记录日志到数据库的时候,可能会发生错误,比如暂时连不上数据库了,那就先记录在文件里面,然后在合适的时候把文件中的记录再转录到数据库中。
可以采用策略模式,把日志记录到数据库和日志记录到文件当作两种记录日志的策略,然后在运行期间根据需要进行动态的切换。
(1)先定义日志策略接口,很简单,就是一个记录日志的方法,示例代码如下:
/**

* 日志记录策略的接口

*/

public interface LogStrategy {

/**

* 记录日志

* @param msg 需记录的日志信息

*/

public void log(String msg);

}

(2)实现日志策略接口,先实现默认的数据库实现,假设如果日志的长度超过长度就出错,制造错误的是一个最常见的运行期错误,示例代码如下:

/**

* 把日志记录到数据库

*/

public class DbLog implements LogStrategy{

public void log(String msg) {

//制造错误

if(msg!=null && msg.trim().length()>5){

int a = 5/0;

}

System.out.println("现在把 '"+msg+"' 记录到数据库中");

}

}

接下来实现记录日志到文件中去,示例代码如下:

/**

* 把日志记录到文件

*/

public class FileLog implements LogStrategy{

public void log(String msg) {

System.out.println("现在把 '"+msg+"' 记录到文件中");

}

}

(3)接下来定义使用这些策略的上下文,注意这次是在上下文里面实现具体策略算法的选择,所以不需要客户端来指定具体的策略算法了,示例代码如下:





(4)看看现在的客户端,没有了选择具体实现策略算法的工作,变得非常简单,故意多调用一次,可以看出不同的效果,示例代码如下:





参考资料:《Head First 设计模式》
http://www.uml.org.cn/sjms/201009092.asp  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: