设计模式是一套被反复使用,多数人知晓,经过分类编目的,代码设计的总结,也可以说是前人的智慧结晶。学习设计模式能让我们对一些应用场景使用相同的套路达到很好的效果,我会不定时更新一些自己
对设计模式的理解的文章,从定义,实现,应用场景来说说设计模式,今天我要说的对象是策略模式
一:定义
策略模式(Strategy Pattern):定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。策略模式是一种对象行为型模式
标准的策略模式通常包含以下三个成员
1.环境类Context:或者说使用策略模式的类。通常需要引用一个实例化的具体策略类的实例
2.AbstractStrategy抽象的策略类或者接口:定义一个抽象的算法方法
3.ConcreteStrategy具体的策略类:实现具体的算法
结构类图:
二:实现
由于抽象的策略父类或接口中只定义了一个抽象的算法,这个算法不同实现就是不通具体策略类,而使用的时候,只需要将具体策略类的实例指向父类的应用就可以了,这样当新增具体的
策略类或者更改策略算法都不需要改变原有的代码,符合开闭原则
在一个点餐系统中,有普通用户,无卡会员,有卡会员三种用户,同一个价格商品,
1.游客收取100%的费用,但是赠送一张会员体验券
2.无卡会员可以享受3块的减免,并且积分
3.会员打9.5折,并且有积分
/**
*抽象折扣策略
*/
abstract class DiscountStrategy{
public abstract void calculate(double price);
}
/**
* 游客策略
*/
class TouristDiscountStrategy extends DiscountStrategy{
@Override
public void calculate(double price) {
System.out.println("游客点餐价格没有优惠:"+price);
System.out.println("该游客获得一张会员体验券");
}
}
/**
* 无卡会员策略
*/
class NotCardMemberDiscountStrategy extends DiscountStrategy{
@Override
public void calculate(double price) {
System.out.println("无卡会员点餐价格优惠3块,原价:"+price+",现价:"+(price-3));
System.out.println("该无卡会员获得积分");
}
}
/**
* 会员点餐策略
*/
class MemberDiscountStrategy extends DiscountStrategy{
@Override
public void calculate(double price) {
System.out.println("无卡会员点餐打9.5折,原价:"+price+",现价:"+(price*0.95));
System.out.println("该会员获得积分");
}
}
/**
* 环境类,使用具体策略
*/
class Context{
private DiscountStrategy discount;
private double price;
public Context(double price) {
this.price = price;
}
public DiscountStrategy getDiscount() {
return discount;
}
public void buy(){
discount.calculate(price);
}
public void setDiscount(DiscountStrategy discount) {
this.discount = discount;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
/**
* 测试
* @param fd
*/
public static void main(String[] fd){
double price=100;//原价一百
Context context=new Context(price);
DiscountStrategy discount=new TouristDiscountStrategy();
context.setDiscount(discount);
context.buy();
discount=new NotCardMemberDiscountStrategy();
context.setDiscount(discount);
context.buy();
discount=new MemberDiscountStrategy();
context.setDiscount(discount);
context.buy();
}
}
结果打印:
游客点餐价格没有优惠:100.0
该游客获得一张会员体验券
无卡会员点餐价格优惠3块,原价:100.0,现价:97.0
该无卡会员获得积分
无卡会员点餐打9.5折,原价:100.0,现价:95.0
该会员获得积分
三:应用场景
(1) 一个系统需要动态地在几种算法中选择一种,那么可以将这些算法封装到一个个的具体算法类中,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一
的接口,根据“里氏代换原则”和面向对象的多态性,客户端可以选择使用任何一个具体算法类,并只需要维持一个数据类型是抽象算法类的对象
(2) 一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难
以维护的多重条件选择语句。
(3) 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法与相关的数据结构,可以提高算法的保密性与安全性。