什么是策略模式
通俗的来说。策略模式( Strategy Pattern)就是将算法封装到具有共同接口的独立类中,以独立与客户端,客户端可以灵活的使用或替换算法族里面不同的算法,降低了耦合性。这种类型的设计模式属于行为型模式。
这算法体现了几个设计原则:
- 把变化的代码从不变的代码中分离出来;
- 定义了策略接口,针对接口编程而不是具体类;
- 客户通过组合方式使用策略,而不是使用继承。
引入案例
某购物网站,用户分为plus会员和普通会员,plus会员买任何商品都可以打95折,而且普通会员不打折。现在需要实现两种会员对相同商品的结算功能。
传统方式的问题分析
想要学习一个设计模式,首要的就是了解这个设计模式解决什么。
当我们没有学习策略模式的时候,我们想要去实现不同的方案,常常会考虑使用继承的方案。在这里也就是,把商品作为父类,把不同用户购买商品作为子类,从而实现不同的折扣策略。但继承会带来的问题:对类的局部改动,尤其超类的局部改动,会影响其他部分,会有溢出效应。如果再细分plus会员的不同级别,那无疑子类会重写父类的大多实现的方案,也就是耦合性太高的问题。这个时候我们就可以使用策略模式去解决这些问题。
类图
- Strategy是策略接口,定义了了具体策略的方法
- Discount95类Discount00类是,具体策略类,实现了策略的方法
- Shop类是抽象商品类,聚合了策略接口;
- Book类是具体商品类
代码
策略接口Strategy
package strategy;
public interface Strategy {
void count(double price);//计算的方法
double getcount();//得到计算结果
}
具体策略类Discount95
package strategy;
public class Discount95 implements Strategy {
private double price;
@Override
public void count(double price) {
// TODO Auto-generated method stub
this.price = price * 0.95;//计算价钱为95折
}
@Override
public double getcount() {
// TODO Auto-generated method stub
return price;
}
}
具体策略类Discount00
package strategy;
public class Discount00 implements Strategy {
private double price;
@Override
public void count(double price) {
// TODO Auto-generated method stub
this.price=price;//计算价钱为原价
}
@Override
public double getcount() {
// TODO Auto-generated method stub
return price;
}
}
抽象商品类Shop
package strategy;
public abstract class Shop {
Strategy strategy ;//聚合一个策略
double price;
String name;
public Shop(double price, String name) {
super();
this.price = price;
this.name = name;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void count() {
strategy.count(price);
this.price=strategy.getcount();
}
public abstract void display();
}
具体商品类Book
package strategy;
public class Book extends Shop{
public Book(double price, String name) {
super(price, name);
// TODO Auto-generated constructor stub
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println(name+price+"元");
}
}
客户端Client
package strategy;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Book book =new Book(20, "《沉默的巡游》");
System.out.println("plus会员购买");
book.setStrategy(new Discount95());
book.count();
book.display();
Book book2 =new Book(20, "《沉默的巡游》");
System.out.println("普通会员购买");
book2.setStrategy(new Discount00());
book2.count();
book2.display();
}
}
运行截图
总结
- 策略模式关键是,分离代码变的部分与不变的部分
- 策略模式的核心思想是,多用组合聚合,少用继承
- 客户端增加行为不需要修改原代码,只需要增加对应的策略
- 独立的 Strategy类使它易于切换、易于理解、易于扩展
- 如果策略过多可能会造成类爆炸