转载文章地址: https://www.jianshu.com/p/3bcf55cf83d3
一、业务场景:
1、有一个鸟类,鸟有共同的属性,比如飞和叫,不同的叫声,可以通过子类重写父类的方法进行,当业务扩展,鸟还有进食的属性,
但是不同的鸟类,吃的东西不一样,就比如有的类中,不需要此方法,该怎么解决呢?a.子类重写父类方法,但是当有多个类实现时,
修改比较麻烦,b.定义吃的统一接口,不同的吃的食物方式实现吃的统一接口,当不同种类的鸟进食时,调用不同的实现类,实现不同
类的鸟进行不同吃的方式;
2、当一个旧的类,需要在主类中添加一个方法,所有的子类继承之后,都会调用这个方法,但是并不是所有的子类都需要实现这个方法,这时候就需要想新的办法了:
1)、在每个子类中去重写这个新方法---》太麻烦,而且代码复用性不高,
2)、定义有一个行为(interface),行为的具体实现方式不一样,列入鸭子叫:Gaga叫、gugu叫,子类实现的具体行为不一样,则最终表达的方式就不一样
二、类图
三、实现通用代码:
class Client { public static void main(String[] args) { //选择一个具体策略 IStrategy strategy = new ConcreteStrategyA(); //来一个上下文环境 Context context = new Context(strategy); //客户端直接让上下文环境执行算法 context.algorithm(); } //抽象策略类 Strategy interface IStrategy { void algorithm(); } //具体策略类 ConcreteStrategy static class ConcreteStrategyA implements IStrategy { @Override public void algorithm() { System.out.println("Strategy A"); } } //具体策略类 ConcreteStrategy static class ConcreteStrategyB implements IStrategy { @Override public void algorithm() { System.out.println("Strategy B"); } } //上下文环境 static class Context { private IStrategy mStrategy; public Context(IStrategy strategy) { this.mStrategy = strategy; } public void algorithm() { this.mStrategy.algorithm(); } } }
策略者模式实现加减乘除,避免掉使用if..else...等带给代码的冗余性
模式 Whyn 关注 赞赏支持 策略模式 0.723 2018.10.27 23:31:27 字数 1093 阅读 4496 简介 Define a family of algorithms,encapsulate each one,and make them interchangeable. 定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。 策略模式(Strategy Pattern) 也叫 政策模式(Policy Pattern)。指的是对象具备某个行为,但是在不同的场景中,该行为有不同的实现算法。比如一个人的交税比率与他的工资有关,不同的工资水平对应不同的税率。 策略模式 使用的就是面向对象的继承和多态机制,从而实现同一行为在不同场景下具备不同实现。 策略模式 本质:分离算法,选择实现 主要解决 在有多种算法相似的情况下,使用 if...else 或 switch...case 所带来的复杂性和臃肿性。 优缺点 优点 算法多样性,且具备自由切换功能; 有效避免多重条件判断,增强了封装性,简化了操作,降低出错概率; 扩展性良好,策略类遵顼 里氏替换原则,可以很方便地进行策略扩展; 缺点 策略类数量增多,且所有策略类都必须对外暴露,以便客户端能进行选择; 使用场景 针对同一类型问题,有多种处理方式,每一种都能独立解决问题; 算法需要自由切换的场景; 需要屏蔽算法规则的场景; 模式讲解 首先来看下 策略模式 的通用 UML 类图: 策略模式 从 UML 类图中,我们可以看到,策略模式 主要包含三种角色: 上下文角色(Context):用来操作策略的上下文环境,屏蔽高层模块(客户端)对策略,算法的直接访问,封装可能存在的变化; 抽象策略角色(Strategy):规定策略或算法的行为; 具体策略角色(ConcreteStrategy):具体的策略或算法实现; 以下是 策略模式 的通用代码: class Client { public static void main(String[] args) { //选择一个具体策略 IStrategy strategy = new ConcreteStrategyA(); //来一个上下文环境 Context context = new Context(strategy); //客户端直接让上下文环境执行算法 context.algorithm(); } //抽象策略类 Strategy interface IStrategy { void algorithm(); } //具体策略类 ConcreteStrategy static class ConcreteStrategyA implements IStrategy { @Override public void algorithm() { System.out.println("Strategy A"); } } //具体策略类 ConcreteStrategy static class ConcreteStrategyB implements IStrategy { @Override public void algorithm() { System.out.println("Strategy B"); } } //上下文环境 static class Context { private IStrategy mStrategy; public Context(IStrategy strategy) { this.mStrategy = strategy; } public void algorithm() { this.mStrategy.algorithm(); } } } 举个例子 例子:假设现在有两个数与一个运算符,要求使用该运算符操作这两个数。 分析:直接思路:通过判断运算符符号,对这两个数进行运算。代码如下所示: static class Calculator { private static final String SYMBOL_ADD = "+"; private static final String SYMBOL_SUB = "-"; public int calc(int a, int b, final String symbol) { int result = 0; if (SYMBOL_ADD.equals(symbol)) { result = a + b; } else if (SYMBOL_ADD.equals(symbol)) { result = a - b; } return result; } } 但是这样写的话,如果我们现在要扩展乘法*或除法/运算,那么就要在calc方法内增加对应的if...else判断,代码臃肿并且扩展性太低。 而如果采用策略模式,将各种运算符的计算都归并到对应具体策略,这样,就能简化代码并且带来很好的扩展性,具体代码如下: class Client { public static void main(String[] args) { ICalculator calculator = new Add(); Context context = new Context(calculator); int result = context.calc(1,2); System.out.println(result); } interface ICalculator { int calc(int a, int b); } static class Add implements ICalculator { @Override public int calc(int a, int b) { return a + b; } } static class Sub implements ICalculator { @Override public int calc(int a, int b) { return a - b; } } static class Multi implements ICalculator { @Override public int calc(int a, int b) { return a * b; } } static class Divide implements ICalculator { @Override public int calc(int a, int b) { return a / b; } } static class Context { private ICalculator mCalculator; public Context(ICalculator calculator) { this.mCalculator = calculator; } public int calc(int a, int b) { return this.mCalculator.calc(a, b); } } }