策略模式定义:策略模式定义了算法族,将算法分别封装起来,让他们之间可以互相替换。此模式让算法的变化独立于使用算法的客户
我们来看一个商场打折的例子
public interface Discount {
public double reduce(double total);
}
public class Derate implements Discount {
// 8折
public double reduce(double total){
return total * 0.8;
};
}
public class Return implements Discount {
// 满100减少20
public double reduce(double total) {
return total - total / 100 * 20;
}
}
public class Bill {
public double pay(double total, String discountType){
Discount discount = null;
if(discountType.equals("Return"))
discount = new Return();
else if(discountType.equals("Derate"))
discount = new Derate();
if(discount != null)
total = discount.reduce(total);
return total;
}
}
商场的折扣力度是会经常性发生变化的,现有代码为了支持这种变化,只能添加新的实现类,但是仅仅为了支持9折,就需要在已有8折代码的基础上添加新的实现类,既没有体现8折、9折之间逻辑的相似性,也没有很好的复用代码
public interface Discount {
public double reduce(double total);
}
// 打折
public class Derate implements Discount {
private double rate;
public Derate(double rate){
this.rate = rate;
}
public double reduce(double total){
return total * rate;
};
}
// 满减
public class Return implements Discount {
private double collect;
private double reduce;
public Return(double collect, double reduce){
this.collect = collect;
this.reduce = reduce;
}
public double reduce(double total) {
return total - total / collect * reduce;
}
}
public class Bill {
public double pay(double total, String discountType){
Discount discount = null;
if(discountType.equals("Return"))
// 满100减少20
discount = new Return(100, 20);
else if(discountType.equals("Derate"))
// 8折
discount = new Derate(0.8);
if(discount != null)
total = discount.reduce(total);
return total;
}
}
经过修改,同类优惠政策,仅需在构造时传入不同的参数即可适应各种情况,除非出现新的优惠政策,比如每满1000,折扣力度增加5%,才需要新的实现类
我们来看看账单类,调用方负责构造具体实现类的构造,我们一下就会想到使用简单工厂进行封装
public class DiscountFactory {
public static Discount getDiscount(String discountType){
Discount discount = null;
if(discountType.equals("Return"))
// 满100减少20
discount = new Return(100, 20);
else if(discountType.equals("Derate"))
// 8折
discount = new Derate(0.8);
return discount;
}
}
public class Bill {
public double pay(double total, String discountType){
Discount discount = DiscountFactory.getDiscount(discountType);
if(discount != null)
total = discount.reduce(total);
return total;
}
}
这下看起来很“完美”了,但是既然是打了引号的完美,那么就说明还是存在问题的。问题就出在这个DiscountFactory类,这个类从功能上来说很明确,就是用来构造Discount类,但是从实际角度出发,这个类是从现实中的哪种对象或行为抽象而来的呢?从类图中我们可以很明确的发现Bill类即依赖DiscountFactory类,也依赖Discount类,事实上,Bill类只关心折扣,不关心折扣的构建过程,那么我们有没有其它的设计方式,可以使Bill类与DiscountFactory类解耦呢?
public class DiscountStrategy {
private Discount discount;
public DiscountStrategy(String discountType){
if(discountType.equals("Return"))
// 满100减少20
discount = new Return(100, 20);
else if(discountType.equals("Derate"))
// 8折
discount = new Derate(0.8);
}
public double reduce(double total) {
if(discount != null)
total = discount.reduce(total);
return total;
}
}
public class Bill {
public double pay(double total, String discountType){
DiscountStrategy discountStrategy = new DiscountStrategy(discountType);
return discountStrategy.reduce(total);
}
}
从类图就能看出策略模式和工厂模式的差别了,DiscountFactory依赖Discount而DiscountStrategy组合Discount,虽说耦合 变得更高了,但是其实是DiscountStrategy抽象化程度更高了,从本质上说DiscountStrategy其实也可以看做是Discount的一种,同时,调用方的耦合度则更低
public class DiscountStrategy implements Discount{
private Discount discount;
public DiscountStrategy(String discountType){
if(discountType.equals("Return"))
// 满100减少20
discount = new Return(100, 20);
else if(discountType.equals("Derate"))
// 8折
discount = new Derate(0.8);
}
public double reduce(double total) {
if(discount != null)
total = discount.reduce(total);
return total;
}
}