先给出一个情景:编写一个商店收银软件,根据单价和数量计算价格

我们要考虑的

  • 在上面所述的情景中,可能出现商品打折情况
  • 可能出现满减等新情况

使用简单工厂实现

avatar
此处仅给出类图,工厂模式详解见
https://www.xuyuyan.cn/2020/04/23/简单工厂模式
此处使用简单工厂模式存在明显缺陷:
商场会经常性地更改打折额度,每次维护或扩展新的收费方式都要改动工厂

策略模式UML图

avator

策略模式代码实现(Java)

策略接口

1
2
3
4
public interface PriceStrategy {
// 价格计算
public abstract double getPrice(int num, double price);
}

策略方法

1
2
3
4
5
6
public class ConcretePriceStrategyA implements PriceStrategy {
@Override
public double getPrice(int num, double price) {
return num * price * 0.8;
}
}
1
2
3
4
5
6
public class ConcretePriceStrategyB implements PriceStrategy {
@Override
public double getPrice(int num, double price) {
return num * price;
}
}

上下文

1
2
3
4
5
6
7
8
9
public class Context {
PriceStrategy priceStrategy;
public Context(PriceStrategy priceStrategy) {
this.priceStrategy = priceStrategy;
}
public double ContextInterface(int num, double price) {
return priceStrategy.getPrice(num, price);
}
}

客户端

1
2
3
4
5
public static void main(String[] args) {
Context context = new Context(new ConcretePriceStrategyA());
double price = context.ContextInterface(2, 9.9);
// System.out.println("价格是:" + price);
}

通过以上代码可以发现若是算法较多时,客户端将会存在较复杂的swtich语句,所以通常在算法较多时将策略模式和简单工厂模式结合。

策略模式+简单工厂模式

策略接口和策略类不变
上下文工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ContextFactory {
PriceStrategy priceStrategy = null;
public ContextFactory(String type) {
switch (type) {
case "正常收费" : {
priceStrategy = new ConcretePriceStrategyB();
break;
}
case "8折" : {
priceStrategy = new ConcretePriceStrategyA();
}
}
}
public double ContextInterface(int num, double price) {
return priceStrategy.getPrice(num, price);
}
}

客户端

1
2
3
4
5
public static void main(String[] args) {
ContextFactory contextFactory = new ContextFactory("正常收费");
double price = contextFactory.ContextInterface(2, 9.9);
// System.out.println("价格是:" + price);
}

策略模式的优势

  1. 减少耦合:以相同的方式j调用所有算法,减少了算法类和使用算法类张子健的耦合
  2. 可重用:Strategy类层次为Conext定义了可重用的d算法,继承有助于析取公共功能
  3. 简化单元测试:每个算法都有独立的类,可以单独测试

策略模式的缺点

  1. 即使和工厂模式结合后仍存在工厂模式的缺点:工厂类的变动频率过高

本文部分内容改编于程杰老师的《大话设计模式》