策略模式(八)
策略模式
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
介绍
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:实现同一个接口。
应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 3、JAVA AWT 中的 LayoutManager。
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
使用场景: 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中选择一种。 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

package com.tzy.Strategy.com.old; /** * @author Heaton * @date 2018/5/7 21:59 * @describe 策略接口 */ public interface Strategy { //加密 public void encrypt(); }
package com.tzy.Strategy.com.old; public class MDSStrategy implements Strategy { public void encrypt() { System.out.println("ִ已进行MDS加密"); } }
package com.tzy.Strategy.com.old; public class MD5Strategy implements Strategy { public void encrypt() { System.out.println("ִ已进行MD5加密"); } }
package com.tzy.Strategy.com.old;
/**
* @author Heaton
* @date 2018/5/7 22:01
* @describe 策略 和装饰很像 装饰是对功能的添加,而策略是对功能的选择,
* 层级上装饰更深。装饰要保留原有方法做扩展,需要实现以前的接口
*/
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void encrypt() {
this.strategy.encrypt();
}
}
package com.tzy.Strategy.com.old; public class MainClass { public static void main(String[] args) { // Strategy stra = new MDSStrategy(); // stra.encrypt(); Context context = new Context(new MDSStrategy()); context.encrypt(); } }

在来个优惠案例
package com.tzy.Strategy.com.news; public interface Strategy { public double cost(double num); }
package com.tzy.Strategy.com.news; public class StrategyA implements Strategy { public double cost(double num) { return num * 0.8; } }
package com.tzy.Strategy.com.news; public class StrategyB implements Strategy { public double cost(double num) { if(num >= 200) { return num - 50; } return num; } }
package com.tzy.Strategy.com.news; public class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public double cost(double num){ return this.strategy.cost(num); } }
package com.tzy.Strategy.com.news; public class MainClass { public static void main(String[] args) { double num = 200; Context context = new Context(new StrategyB()); double newNum = context.cost(num); System.out.println("优惠后" + newNum + "元"); } }

************************Demo 鸭子游戏

package com.tzy.Strategy.com.demo.oo; public abstract class Duck { public Duck() { } public void Quack() { System.out.println("~~gaga~~"); } public abstract void display(); public void swim() { System.out.println("~~im swim~~"); } public void Fly() { System.out.println("~~im fly~~"); } }
package com.tzy.Strategy.com.demo.oo; public class GreenHeadDuck extends Duck { @Override public void display() { System.out.println("**GreenHead**"); } public void Fly() { System.out.println("~~no fly~~"); } }
package com.tzy.Strategy.com.demo.oo; public class RedHeadDuck extends Duck { @Override public void display() { System.out.println("**RedHead**"); } public void Fly() { System.out.println("~~good fly~~"); } }
package com.tzy.Strategy.com.demo.oo; public class StoneDuck extends Duck { @Override public void display() { System.out.println("**StoneDuck**"); } public void Quack() { System.out.println("~~no gaga~~"); } public void swim() { System.out.println("~~no swim~~"); } public void Fly() { System.out.println("~~no fly~~"); } }
package com.tzy.Strategy.com.demo.oo; public class StimulateDuck { public static void main(String[] args) { GreenHeadDuck mGreenHeadDuck = new GreenHeadDuck(); RedHeadDuck mRedHeadDuck = new RedHeadDuck(); mGreenHeadDuck.display(); mGreenHeadDuck.Fly(); mGreenHeadDuck.Quack(); mGreenHeadDuck.swim(); mRedHeadDuck.display(); mRedHeadDuck.Quack(); mRedHeadDuck.swim(); mRedHeadDuck.Fly(); // mGreenHeadDuck.Fly(); //mRedHeadDuck.Fly(); } }

以上代码可以看出,超类鸭子有各种功能,绿头鸭和红头鸭有的功能不同,如果在超类里加一个飞行的方法,那么红头鸭就要重写说明自己不会飞,不然就会出现溢出效应,
而且如果我们在做一个鸭子,那么也需要去重写所有超类有的方法,这种继承关系是不科学的。

用策略模式的思想:分别封装行为接口,实现算法组,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为算法的变化
独立于算法的使用者。
嘎嘎叫的行为组
package com.tzy.Strategy.com.demo.quackbehavior; public interface QuackBehavior { void quack(); };
package com.tzy.Strategy.com.demo.quackbehavior; public class NoQuackBehavior implements QuackBehavior { @Override public void quack() { // TODO Auto-generated method stub System.out.println("__NoQuack__"); } }
package com.tzy.Strategy.com.demo.quackbehavior; public class GeGeQuackBehavior implements QuackBehavior { @Override public void quack() { // TODO Auto-generated method stub System.out.println("__GeGe__"); } }
package com.tzy.Strategy.com.demo.quackbehavior; public class GaGaQuackBehavior implements QuackBehavior { @Override public void quack() { // TODO Auto-generated method stub System.out.println("__GaGa__"); } }
飞行行为组
package com.tzy.Strategy.com.demo.flybehavior; public interface FlyBehavior { void fly(); }
package com.tzy.Strategy.com.demo.flybehavior; public class BadFlyBehavior implements FlyBehavior { @Override public void fly() { // TODO Auto-generated method stub System.out.println("--BadFly--"); } }
package com.tzy.Strategy.com.demo.flybehavior; public class GoodFlyBehavior implements FlyBehavior { @Override public void fly() { // TODO Auto-generated method stub System.out.println("--GoodFly--"); } }
package com.tzy.Strategy.com.demo.flybehavior; public class NoFlyBehavior implements FlyBehavior { @Override public void fly() { // TODO Auto-generated method stub System.out.println("--NoFly--"); } }
重点来了,操作类
package com.tzy.Strategy.com.demo.duck; import com.tzy.Strategy.com.demo.flybehavior.FlyBehavior; import com.tzy.Strategy.com.demo.quackbehavior.QuackBehavior; public abstract class Duck { FlyBehavior mFlyBehavior; QuackBehavior mQuackBehavior; public Duck() { } public void Fly() { mFlyBehavior.fly(); } public void Quack() { mQuackBehavior.quack(); } public abstract void display(); public void SetQuackBehavoir(QuackBehavior qb) { mQuackBehavior = qb; } public void SetFlyBehavoir(FlyBehavior fb) { mFlyBehavior = fb; } public void swim() { System.out.println("~~im swim~~"); } }
package com.tzy.Strategy.com.demo.duck; import com.tzy.Strategy.com.demo.flybehavior.GoodFlyBehavior; import com.tzy.Strategy.com.demo.quackbehavior.GaGaQuackBehavior; public class GreenHeadDuck extends Duck { public GreenHeadDuck() { mFlyBehavior = new GoodFlyBehavior(); mQuackBehavior = new GaGaQuackBehavior(); } @Override public void display() { // TODO Auto-generated method stub System.out.println("**GreenHead**"); } }
package com.tzy.Strategy.com.demo.duck; import com.tzy.Strategy.com.demo.flybehavior.BadFlyBehavior; import com.tzy.Strategy.com.demo.quackbehavior.GeGeQuackBehavior; public class RedHeadDuck extends Duck { public RedHeadDuck() { mFlyBehavior = new BadFlyBehavior(); mQuackBehavior = new GeGeQuackBehavior(); } @Override public void display() { // TODO Auto-generated method stub System.out.println("**RedHead**"); } }
测试
package com.tzy.Strategy.com.demo; import com.tzy.Strategy.com.demo.duck.Duck; import com.tzy.Strategy.com.demo.duck.GreenHeadDuck; import com.tzy.Strategy.com.demo.duck.RedHeadDuck; import com.tzy.Strategy.com.demo.flybehavior.NoFlyBehavior; import com.tzy.Strategy.com.demo.quackbehavior.NoQuackBehavior; public class StimulateDuck { public static void main(String[] args) { Duck mGreenHeadDuck = new GreenHeadDuck(); Duck mRedHeadDuck = new RedHeadDuck(); mGreenHeadDuck.display(); mGreenHeadDuck.Fly(); mGreenHeadDuck.Quack(); mGreenHeadDuck.swim(); mRedHeadDuck.display(); mRedHeadDuck.Fly(); mRedHeadDuck.Quack(); mRedHeadDuck.swim(); mRedHeadDuck.display(); mRedHeadDuck.SetFlyBehavoir(new NoFlyBehavior()); mRedHeadDuck.Fly(); mRedHeadDuck.SetQuackBehavoir(new NoQuackBehavior()); mRedHeadDuck.Quack(); } }

总结:
比如鸭子都会游泳,但是不一定都会飞,叫声也可能不同;
或者动物类,狗和狼,叫声可能不同,抽出来做行为组,但是都会跑,那么要不要把跑拿出来,要啊,因为要是来个新需求鱼,那么他只会游泳,所以可以抽出一个行为组叫移动。
1分析项目中变化部分与不变部分
2多用组合少用继承;用行为类组合,而不是行为的继承。更有弹性
3设计模式有没有相应的库直接使用?--有些库或框架本身就是某种设计模式设计的
4如果找不到适用的模式怎么办? --只能OOP了
您的资助是我最大的动力!
金额随意,欢迎来赏!
浙公网安备 33010602011771号