读《研磨设计模式》-代码笔记-策略模式-Strategy

[b]声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客[url]http://chjavach.iteye.com/[/url][/b]




/*
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化

简单理解:
1、将不同的策略提炼出一个共同接口。这是容易的,因为不同的策略,只是算法不同,需要传递的参数(如果需要)和返回值(如果有)都是一样的
2、需要用到策略的类,持有这个接口。在计算时,就可以转调策略接口来实现

大体框架是这样:
interface IStrategy {
double calculatePrice(double primeCost);
}

class Context{
private IStrategy strategy; 由于这里是面向接口,所有切换策略很方便
public double caculate(double primeCost) {
return strategy.caculatePrice(primeCost);
}
}
……
……

策略模式的缺点也很易见:策略太多,会造成有多个策略类

*/

/**
* 根据不同的优惠政策计算价格
* @param primeCost 商品原价
*/
interface IStrategy {

double calculatePrice(double primeCost);

}


class NormalCustomerStrategy implements IStrategy {

public double calculatePrice(double primeCost) {
System.out.println("对于普通用户,不打折,返回原价:");
return primeCost;
}

}


class RegularCustomerStrategy implements IStrategy {

public double calculatePrice(double primeCost) {
System.out.println("对于老客户,打95折:");
return primeCost * (1 - 0.05);
}

}


//对应策略模式中的Context
class Price {

private IStrategy strategy;

public Price(IStrategy strategy) {
this.strategy = strategy;
}

//如果primeCost是作为类Price的一个field,那么给IStrategy的calculatePrice传递参数时候,
//就是传递整个Price对象了
public double getRealPrice(double primeCost) {
return this.strategy.calculatePrice(primeCost);
}

}


/*
* 作一个扩展:
* 老客户在打95折的基础上,再便宜10块钱
* 另外,将商品原价作为Price类的一个field
* 有两种实现
*/
interface IStrategyB {

//传递整个Context对象
double calculatePrice(PriceContext priceContext);

}


class PriceContext {

private IStrategyB strategy;
private double primeCost; //将商品原价作为Price类的一个field

public PriceContext(IStrategyB strategy, double primeCost) {
this.strategy = strategy;
this.primeCost = primeCost;
}

public double getPrimeCost() {
return this.primeCost;
}

public double getRealPrice() {
//这里是把整个Context传递进去了
return this.strategy.calculatePrice(this);
}
}


//”老客户打95折“
class RegularCustomerStrategyB implements IStrategyB {

public double calculatePrice(PriceContext priceContext) {
double primeCost = priceContext.getPrimeCost();
return primeCost * (1 - 0.05);
}

}

//”再便宜10块钱“
//1.extends strategy.要额外减少的数据来自strategy
class HappyRegularCustomerStrategyB extends RegularCustomerStrategyB {

private double diff;

public HappyRegularCustomerStrategyB(double diff) {
this.diff = diff;
}

public double calculatePrice(PriceContext priceContext) {
System.out.println("对老客户实行打折后再优惠的策略。差价来自Strategy:");
return super.calculatePrice(priceContext) - diff;
}
}

//2.extends Context.要额外减少的数据来自Price(Context)。这样,所有数据都来自Context,较为统一
class HappyPriceContext extends PriceContext {

private double diff;

public HappyPriceContext(IStrategyB strategy, double primeCost, double diff) {
super(strategy, primeCost);
this.diff = diff;
}

public double getRealPrice() {
System.out.println("对老客户实行打折后再优惠的策略。差价来自Context:");
return super.getRealPrice() - diff;
}

}


/**
* 书上提到策略模式的一个应用:“容错恢复机制”
* 正常情况下是一种策略,出错了又是另一种策略
* 书上给的例子是,记录日志到数据库,若出错了(例如连不上数据库),那先记录到文件中,以后再保存到数据库
*/

interface ILogStrategy {

void log(String message);

}

class DatabaseLogStrategy implements ILogStrategy {

public void log(String message) {
//模拟出错的情况
if (message != null && message.length() > 5) {
int i = 5 / 0;
}
System.out.println("将以下日志信息记录到数据库中:" + message);
}

}


class FileSystemLogStrategy implements ILogStrategy {

public void log(String message) {
System.out.println("将以下日志信息记录到文件中:" + message);
}

}


//这里策略的选择在Context里实现
class LogContext {

//private ILogStrategy strategy;

public void log(String message) {
ILogStrategy databaseStrategy = new DatabaseLogStrategy();
try {
databaseStrategy.log(message);
} catch (Exception e) {
System.out.print("出错了,将日志信息先保存在文件中:");
ILogStrategy fileStrategy = new FileSystemLogStrategy();
fileStrategy.log(message);
}
}

}


//书上最后提到了策略模式和模板模式结合使用的方法:在模板中定义业务算法的“骨架”,具体算法(策略)由子类实现

/**
* 这个类是用来测试的
*/
public class StrategyPattern {

public static void main(String[] args) {
//测试打折策略
double primeCost = 1000.0;
IStrategy strategy = new NormalCustomerStrategy();
Price price = new Price(strategy);
double realPrice = price.getRealPrice(primeCost );
System.out.println(realPrice);

strategy = new RegularCustomerStrategy();
price = new Price(strategy);
realPrice = price.getRealPrice(primeCost);
System.out.println(realPrice);

System.out.println();

//测试打折再减差价的策略
double diff = 10.0;
HappyRegularCustomerStrategyB happyStrategyB = new HappyRegularCustomerStrategyB(diff); //差价来自Strategy
PriceContext priceContext = new PriceContext(happyStrategyB, primeCost);
realPrice = priceContext.getRealPrice();
System.out.println(realPrice);

RegularCustomerStrategyB strategyB = new RegularCustomerStrategyB();
priceContext = new HappyPriceContext(strategyB, primeCost, diff); //差价来自Context
realPrice = priceContext.getRealPrice();
System.out.println(realPrice);

System.out.println();

//测试记录日志
LogContext logContext = new LogContext();
logContext.log("hello");
logContext.log("hellooo");
}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值