23种设计模式之二(策略模式)

策略模式:(分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象)

原则:

  分离变化部分,封装接口,基于接口编程各种功能。此模式让行为算法的变化独立于算法的使用者。

  

举例说明:

  分别封装行为接口:FlyBehavior、QuackBehavior;

  实现算法族:BadFlyBehavior、GoodFlyBehavior、NoFlyBehavior;GaGaQuackBehavior、GeGeQuackBehavior、NoQuackBehavior;

  超类里放行为接口对象:

    

  在子类里具体设定行为对象:

    

    

  在使用的时候:

    

例子结构:

1 package com.java.hexter.stimulateduck.flybehavior;
2 
3 public interface FlyBehavior {
4     void fly();
5 }
FlyBehavior
1 package com.java.hexter.stimulateduck.quackbehavior;
2 
3 public interface QuackBehavior {
4     void quack();
5 };
QuackBehavior
 1 package com.java.hexter.stimulateduck.duck;
 2 
 3 import com.java.hexter.stimulateduck.flybehavior.FlyBehavior;
 4 import com.java.hexter.stimulateduck.quackbehavior.QuackBehavior;
 5 
 6 public abstract class Duck {
 7 
 8     FlyBehavior mFlyBehavior;
 9     QuackBehavior mQuackBehavior;
10 
11     public Duck() {
12 
13     }
14 
15     public void Fly() {
16         mFlyBehavior.fly();
17     }
18 
19     public void Quack() {
20         mQuackBehavior.quack();
21     }
22 
23     public abstract void display();
24 
25     //为了增加代码的灵活性,可以自己设定鸭子叫的方式
26     public void SetQuackBehavoir(QuackBehavior qb) {
27         mQuackBehavior = qb;
28     }
29     public void SetFlyBehavoir(FlyBehavior fb) {
30         mFlyBehavior = fb;
31     }
32 
33     public void swim() {
34         System.out.println("~~im swim~~");
35     }
36 }
Duck
 1 package com.java.hexter.stimulateduck.flybehavior;
 2 
 3 
 4 
 5 public class    BadFlyBehavior implements FlyBehavior
 6 {
 7     @Override
 8     public void fly() {
 9         // TODO Auto-generated method stub
10         System.out.println("--BadFly--");
11     }
12 }
BadFlyBehavior
 1 package com.java.hexter.stimulateduck.flybehavior;
 2 
 3 
 4 public class    GoodFlyBehavior implements FlyBehavior
 5 {
 6 
 7     @Override
 8     public void fly() {
 9         // TODO Auto-generated method stub
10         System.out.println("--GoodFly--");
11     }
12     
13 }
GoodFlyBehavior
 1 package com.java.hexter.stimulateduck.flybehavior;
 2 
 3 
 4 public class    NoFlyBehavior implements FlyBehavior
 5 {
 6     @Override
 7     public void fly() {
 8         // TODO Auto-generated method stub
 9         System.out.println("--NoFly--");
10     }
11 }
NoFlyBehavior
 1 package com.java.hexter.stimulateduck.quackbehavior;
 2 
 3 
 4 public    class GaGaQuackBehavior implements QuackBehavior
 5 {
 6 
 7     @Override
 8     public void quack() {
 9         // TODO Auto-generated method stub
10         System.out.println("__GaGa__");
11     }
12     
13 }
GaGaQuackBehavior
 1 package com.java.hexter.stimulateduck.quackbehavior;
 2 
 3 
 4 public    class GeGeQuackBehavior implements QuackBehavior
 5 {
 6 
 7     @Override
 8     public void quack() {
 9         // TODO Auto-generated method stub
10         System.out.println("__GeGe__");
11     }
12     
13 }
GeGeQuackBehavior
 1 package com.java.hexter.stimulateduck.quackbehavior;
 2 
 3 
 4 public    class NoQuackBehavior implements QuackBehavior
 5 {
 6 
 7     @Override
 8     public void quack() {
 9         // TODO Auto-generated method stub
10         System.out.println("__NoQuack__");
11     }
12     
13 }
NoQuackBehavior
 1 package com.java.hexter.stimulateduck.duck;
 2 
 3 import com.java.hexter.stimulateduck.flybehavior.GoodFlyBehavior;
 4 import com.java.hexter.stimulateduck.quackbehavior.GaGaQuackBehavior;
 5 
 6 public class GreenHeadDuck extends Duck {
 7 
 8     public GreenHeadDuck() {
 9         mFlyBehavior = new GoodFlyBehavior();
10         mQuackBehavior = new GaGaQuackBehavior();
11     }
12 
13     @Override
14     public void display() {
15         // TODO Auto-generated method stub
16         System.out.println("**GreenHead**");
17     }
18 
19 }
GreenHeadDuck
 1 package com.java.hexter.stimulateduck.duck;
 2 
 3 import com.java.hexter.stimulateduck.flybehavior.BadFlyBehavior;
 4 
 5 import com.java.hexter.stimulateduck.quackbehavior.GeGeQuackBehavior;
 6 
 7 public class RedHeadDuck extends Duck {
 8 
 9     public RedHeadDuck() {
10         mFlyBehavior = new BadFlyBehavior();
11         mQuackBehavior = new GeGeQuackBehavior();
12     }
13 
14     @Override
15     public void display() {
16         // TODO Auto-generated method stub
17         System.out.println("**RedHead**");
18     }
19 
20 }
RedHeadDuck
 1 package com.java.hexter.stimulateduck;
 2 
 3 import com.java.hexter.stimulateduck.duck.Duck;
 4 import com.java.hexter.stimulateduck.duck.GreenHeadDuck;
 5 import com.java.hexter.stimulateduck.duck.RedHeadDuck;
 6 import com.java.hexter.stimulateduck.flybehavior.NoFlyBehavior;
 7 import com.java.hexter.stimulateduck.quackbehavior.NoQuackBehavior;
 8 
 9 
10 public class StimulateDuck {
11 
12     public static void main(String[] args) {
13 
14         Duck mGreenHeadDuck = new GreenHeadDuck();
15         Duck mRedHeadDuck = new RedHeadDuck();
16 
17         mGreenHeadDuck.display();
18         mGreenHeadDuck.Fly();
19         mGreenHeadDuck.Quack();
20         mGreenHeadDuck.swim();
21 
22         mRedHeadDuck.display();
23         mRedHeadDuck.Fly();
24         mRedHeadDuck.Quack();
25         mRedHeadDuck.swim();
26         mRedHeadDuck.display();
27         mRedHeadDuck.SetFlyBehavoir(new NoFlyBehavior());
28         mRedHeadDuck.Fly();
29         mRedHeadDuck.SetQuackBehavoir(new NoQuackBehavior());
30         mRedHeadDuck.Quack();
31     }
32 
33 }
StimulateDuck

输出结果:

**GreenHead**
--GoodFly--
__GaGa__
~~im swim~~
**RedHead**
--BadFly--
__GeGe__
~~im swim~~
**RedHead**
--NoFly--
__NoQuack__

例子该种方式实现的好处:新增行为简单,行为类更好的复用,组合更方便。既有继承带来的复用好处,没有挖坑

注意:

  1.认真分析策略中变化部分与不变部分;

  2.多用组合,少用继承;用行为类组合,而不是行为的继承;这样做更有弹性。

优点:
  (1)策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。
  (2)使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。
  (3)多种不同解决方案动态切换,起到改变对象行为的效果。
缺点:
  (1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。

  (2)由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。

应用场景:

  1、针对同一种问题的多种处理方式、仅仅是因为具体行为有差别时;
  2、需要安全的封装多种同一类型的操作时;
  3、出现同一抽象类有多个子类,而又需要使用if-else或者switch-case来选择具体子类时。

原文地址:https://www.cnblogs.com/mmzs/p/7663661.html