简介
- 策略模式定义了算法家族,分别封装起来,让他们之间可以相互替换。此模式让算法变化不会影响到使用算法的客户。
- 策略模式的组成:
- 抽象策略类:定义了策略的通用接口。
- 具体策略类:包装了相关的算法和行为。
- 上下文环境:持有一个策略类的引用,最终给客户端调用。
实例
-
本Demo的UML图:
UML图.png
- CashSuper:抽象策略类,定义了抽象方法calCash()。
- CashNormal等:具体策略类,包装了不同的算法行为。
- CashContext:上下文环境,持有CashSuper对象。
- 具体实现如下:
- CashContext:
public class CashContext { private CashSuper mCash; public CashContext(CashSuper mCash) { this.mCash = mCash; } public double getResult(double a) { return mCash.calCash(a); } }
- CashSuper:
public abstract class CashSuper { public abstract double calCash(double a); }
- CashNormal:
public class CashNormal extends CashSuper { @Override public double calCash(double a) { return a; } }
- CashDisc:
public class CashDisc extends CashSuper { private double pre = 1.0; public CashDisc(double pre) { this.pre = pre; } @Override public double calCash(double a) { return a * pre; } }
- CashSub:
public class CashSub extends CashSuper { private double full; private double sub; public CashSub(double full, double sub) { this.full = full; this.sub = sub; } @Override public double calCash(double a) { if (a >= full) { a = a - (a/full) * sub; } return a; } }
- CashMain:测试类
public class CashMain { public static void main(String args[]) { CashContext context = null; switch (args[0]) { case "正常收费": context = new CashContext(new CashNormal()); break; case "满800减300": context = new CashContext(new CashSub(800,300)); break; case "打8折": context = new CashContext(new CashDisc(0.8)); break; } if (context != null) { System.out.print("单价800的商品售价:" + context.getResult(800)); } } }
- 运行结果:
单价800的商品售价:640.0
Process finished with exit code 0
和简单工厂模式的结合
- 将选择算法策略的操作放在Context中,即把工厂类的功能整合在Context类,可将客户端代码与具体的策略选择和执行代码分割开来。
- 修改上个Demo中的CashContext:
public class CashContext {
private CashSuper mCash;
public CashContext(String strategy) {
switch (strategy) {
case "正常收费":
mCash = new CashNormal();
break;
case "满800减300":
mCash = new CashSub(800,300);
break;
case "打8折":
mCash = new CashDisc(0.8);
break;
}
}
public double getResult(double a) {
return mCash.calCash(a);
}
}
- 客户端代码:
public class CashMain {
public static void main(String args[]) {
CashContext context = new CashContext(args[0]);
// switch (args[0]) {
// case "正常收费":
// context = new CashContext(new CashNormal());
// break;
// case "满800减300":
// context = new CashContext(new CashSub(800,300));
// break;
// case "打8折":
// context = new CashContext(new CashDisc(0.8));
// break;
// }
if (context != null) {
System.out.print("单价800的商品售价:" + context.getResult(800));
}
}
}
策略模式和工厂模式的对比
- 工厂模式相当于黑盒子,我们并不关心产品是如何被创建出来的,只要给我这样产品就好。而策略模式相当于白盒子,你需要决定如何调用Context类中的策略。
- 工厂模式主要解决的是资源的统一分发,将对象的创建完全独立出来,让对象的创建和具体的使用客户无关。而策略模式为了解决的是策略的切换与扩展,更简洁的说是定义策略族,分别封装起来,让他们之间可以相互替换,策略模式让策略的变化独立于使用策略的客户。
策略模式的优缺点
- 优点:
- 策略模式封装了一系列算法,这些算法完成的都是相同的工作,只是实现不同,它可以用相同的方式去调用所有的算法,减少了各算法与使用算法的类之间的耦合。
- 策略模式拥有不同的算法类,简化了单元测试。
- 策略模式将不同的行为封装在一个个独立的Strategy类中,消除了条件语句。(如果全部行为放在一个类,肯定需要用if else语句判断使用的行为)
- 缺点:
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。
- 增加新的策略类还是需要改变客户端中的switch分支条件。
网友评论