四十五:策略模式

策略模式属于对象的行为模式,其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响客户端的情况下发生变化.

问题描述:
假设现在要对不同地图书进行打折,如对所有教材类图书实行每本一元的折扣,对连环画图书每本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
}
}


这里所给出的仅仅是策略模式的最小实现,因此具体策略角色只有一个,一般而言,有意义的策略模式的应用都会涉及到多于一个的具体策略角色。

二:Java语言内部的例子611
(1)AWT中的LayoutManager
java.awt类库需要在运行期间动太地由客户端决定一个Container对象怎么排列它所有的GUI构件,Java语言提供了几种不同的排列方式,包装在不同的类里:BorderLayout,FlowLayout,GridLayout ,GridBagLayout,CardLayout
以上五个类就是具体策略角色,java.awt.Container是环境角色,而java.awt.LayoutManager则提抽象策略角色。
(2)Swing中的Border
........

三:图书折扣的计算
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;
}
}



四:在什么情况下应当使用策略模式
(1)如果在一个系统里面有许多类,它们之间的区别仅仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为
(2)一个系统需要动态地在几种算法中选择一种,那么可以包装到一个个的具体算法类里面,而这些具体的算法类都是一个抽象算法类的子类。换言之,这些具体算法均有统一接口,由于多态性原则,客户端可以选择使用任何一个具体算法类.
(3)如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现,如果使用策略模式把这些行为转移到相应的具体策略类里,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念.

五:策略模式的优缺点
(1)策略模式提供了管理相关算法族的办法,策略类的等级结构定义了一个算法或行为,恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。
(2)策略模式提供了可以替换继承关系的办法.继承会使动态改变算法变得不可能.
(3)策略模式造成很多的策略类,可以使用享元模式来减少对象的数据.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值