文章目录
- 案例展示——Strategy怎么用?
- 深入分析——Strategy是什么?
- Strategy的定义
- Strategy的优点
- Strategy的缺点
- 策略模式的扩展——策略枚举
- 参考
案例展示——Strategy怎么用?
了解一点历史的人都知道商鞅变法,正是由于商鞅变法,奠定了秦国强大的根基,使秦国从一个最弱小的战国迅速成为一个超强战国,奋六世之余烈,终于在秦始皇手上一统天下。可以说,没有商鞅变法,就没有强大的秦国,或许也可以断言,天下将不会由秦朝统一。那么商鞅变法为什么会有这么大的规律呢,现在我们从软件的设计的角度来看看商鞅变法的威力,下面是类图设计:
分析上面的类图:
-
IStrategy:抽象策略类,定义一个执行法律的方法
-
AwardBattle:法律一,鼓励打仗
-
AbolishSlave:法律二,废除奴隶制度
-
DefeatNobility:法律三,推翻贵族的垄断地位,取消封地
-
SYUpdateLaw:商鞅变法,执行法律
看看上面的每一个法律,是不是都透露着变法家的博大情怀。每一个法律就是一个策略,每一次策略的实施都会使秦国发生脱胎换骨的变化。鼓励耕战,使国人争相入军报效国家,国家实力迅速提升;废除奴隶制度,使奴隶得到解放,人人拥护国家,为国效力;最重要的是推翻世族统治,封地收归国有,权利高度集中。正是由于秦国贯彻实施了商鞅变法,才造就了后来的辉煌蓝图。
下面是具体的代码实现:
// 抽象策略类
public interface IStrategy {// 每天政策都需要切实执行public void operate();
}// 法律一:鼓励耕战
public class AwardBattle implements IStrategy {public void operate() {System.out.println("奖励有功战士!");}
}// 法律二:废除奴隶制
public class AbolishSlave implements IStrategy {public void operate() {System.out.println("废除奴隶制度,举国之人皆是国民!");}
}// 法律三:推翻贵族统治
public class DefeatNobility implements IStrategy {public void operate() {System.out.println("推翻世族,人人平等!");}
}// 商鞅变法
public class SYUpdataLaw {// 构造函数中传入要实施的律法private IStrategy strategy;public SYUpdataLaw(IStrategy strategy) {this.strategy = strategy;}// 实施法律public void operate() {this.strategy.operate();}
}// 开始变法
public class Client {public static void main(String[] args) {// 准备好法律,依次颁布实施SYUpdataLaw ul;System.out.println("==========前三年:鼓励打仗========");ul = new SYUpdataLaw(new AwardBattle());// 执行法律ul.operate();System.out.println("==========中三年:废除奴隶制=======");ul = new SYUpdataLaw(new AbolishSlave());// 执行法律ul.operate();System.out.println("==========时机成熟:推翻世族=======");ul = new SYUpdataLaw(new DefeatNobility());// 执行法律ul.operate();}
}// 结果如下:
==========前三年:鼓励打仗========
奖励有功战士!
==========中三年:废除奴隶制=======
废除奴隶制度,举国之人皆是国民!
==========时机成熟:推翻世族=======
推翻世族,人人平等!
上面的例子中就使用到了策略模式,每一个法律就是一个策略,策略用好了,国家就强大了。
深入分析——Strategy是什么?
Strategy的定义
定义: 定义一组算法,将每个算法都封装起来,并且使它们可以相互交换。通用类图设计如下:
-
Context组建:上下文角色,起承上启下的作用,屏蔽高层模块、算法的直接
直接访问,封装可能存在的变化 -
Strategy组建:抽象策略角色,通常是接口,定义每个策略或算法所必须具有的方法和属性
-
ConcreateStrategy组建:具体的策略,实现了Strategy接口
下面是通用代码实现:
// 策略接口
public interface Strategy {// 执行策略public void doSomething();
}// 策略1
public class ConcreateStrategy1 implements Strategy {public void doSomething() {System.out.println("执行策略1");}
}// 策略2
public class ConcreateStrategy2 implements Strategy {public void doSomething() {System.out.println("执行策略2");}
}// 妙计锦囊
public class Context {// 抽象策略private Strategy strategy = null;// 在构造函数中设置具体策略public Context(Strategy strategy) {this.strategy = strategy;}// 执行策略方法public void doAnything() {this.strategy.doSomething();}
}// 实施策略
public class Client {public static void main(String[] args) {// 声明一个具体的策略Strategy strategy = new ConcreateStrategy1();// 造一个锦囊Context context = new Context(strategy);// 执行策略context.doAnything();}
}
Strategy的优点
-
算法可以自由切换
-
避免多重条件判断
-
扩展性良好,新增一个算法只要实现接口就行了
Strategy的缺点
-
策略类数量增多会增加系统的复杂性
-
所有的策略类都需要向外暴露,不利于和高层模块的解耦
策略模式的扩展——策略枚举
直接看代码:
// 枚举的计算类
public enum Calculator {// 加法运算ADD("+") {public int exec(int a, int b) {return a + b;}},// 减法运算SUB("-") {public int exec(int a, int b) {return a - b;}};String value = "";// 定义成员值类型private Calculator(String value) {this.value = value;}// 获得枚举成员的值public String getValue() {return this.value;}// 声明一个抽象函数public abstract int exec(int a, int b);
}// 计算
public class Client {public static void main(String[] args) {// 两个参数int a = 10, b = 20;System.out.println("运算结果为:" + Calculator.ADD.exec(a, b));System.out.println("运算结果为:" + Calculator.SUB.exec(a, b));}
}
程序是什么意思一眼就能看出来,现在来说说什么是枚举策略,下面简单定义一下:
- 是一个枚举类
- 浓缩了策略模式的枚举,换句话说,每一个枚举算法就是策略
参考
《设计模式之禅》