设计模式(一)The Strategy Pattern 策略模式

摘要 策略模式:定义算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的改变独立于使用算法的客户。

设计模式

我们先来看看问题 —— 现在我们需要实现一个模拟鸭子的游戏,游戏中会出现各种各样的鸭子,他们会有不同的飞行方式,同样有不同的鸣叫方式,同时我们要考虑到以后还可能出现更多的各种各样新式的鸭子,那我们该如何来实现呢?

1>我们来试试继承

这是我们的Duck类

?


1

2

3

4

5

6

7

8

9

package my.oschina.net.design.strategy;

public class Duck {

    public void fly(){}

    public void quack(){}

}

现在我们可以通过继承很简单的来完成各种鸭子的实现,我们所要做的就是简单的继承Duck类,实现符合各自特征的fly()方法和quack()方法,像这样写:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

class Rubber extends Duck {  

    public void fly(){

        System.out.println("I can‘t fly!");

     }

    public void quack(){

        System.out.println("Quack");

    }

}

class ModelDuck extends Duck {

    public void fly(){

        System.out.println("I can fly with rocket!");

    }

    public void quack(){

        System.out.println("<<silience>>");

    }

  

}

class XX extends Duck{

     public void fly(){//XX的飞行方法}

     public void quack(//XX的鸣叫方法){}

}

class YY extends Duck{

     public void fly(){//YY的飞行方法}

     public void quack(){//YY的鸣叫方法}

}

class ZZ extends Duck{

     public void fly(){//ZZ的飞行方法}

     public void quack(){//ZZ的鸣叫方法}

}

        .

        .

        .

大家看到问题之所在了吗?每当我们增加一个新的子类(软件的可扩展性!软件升级的过程中这些可是必不可少的哦!),我们必须要被迫检查每一个可能需要覆盖的方法(尽管有的鸭子根本就不会飞,也根本就不会叫,这真是很头疼)。。。你确定这样你可以忍受?不管你能不能,反正我不能!

2>要不我们试试接口吧!

我们定义两个接口——flyable接口和quackable接口,这样会飞的会叫的鸭子可以实现这两个接口,不会的不需要实现这两个接口。看起来不错哦!真的不错吗?不要被忽悠!NO!错,很错!有没有发现这和继承都有一个通病——代码根本是无法复用的存在!一旦代码无法复用就意味着我们要做大量重复无意义的ctrl+c,ctrl+v工作。

那我们到底该肿么做呢?

来,我们先来看看我们在写代码的时候需要尽力遵循的两个设计原则:

a) 原则一:找出代码中可能需要变化的代码,把他们独立出来,不要和不变化的或者变化极小的代码混在一起。

b) 原则二:针对接口编程,不要针对实现编程。

关于上述两个原则的解释:

a)一旦我们将变化的和不变化的代码分割开来,以后我们可以轻易的改动或者扩展这部分的代码而不用担心其他不需要变化的代码会受到影响。

b)上面的两种方法中我们都是在针对实现来编程,一旦我们将代码写下了我们就很难来改变这些行为,我们被实现绑定的死死的,这就导致当我们要修改这些行为的时候我们不得不来这个类中大量修改这些源代码!这对于后期软件的维护工作简直不能忍!(ps.利用多态的原理,我们针对超类型来编程,执行的时候代码会自己选择适当的行为!)

下面我们再看第三个设计原则

c)多用组合少用继承,这样我们可以在运行时动态改变类的各种行为,这听起来真的很不错哦!

3>使用策略模式

好吧!入正题吧!废话多了点。现在我们来看看使用策略模式的实现方法。

策略模式——定义算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的改变独立于使用算法的客户。

一切看代码:

这是Duck类

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

package my.oschina.net.design.strategy;

/**

 * 我们不变的或者是变动可能性不大的方法写在父类中(display)

 * 把以后可能会变化的方法抽取出来例如这里的fly与quack

 

 * @author Eswin

 *

 */

public class Duck {

//声明两个“接口”类型的变量用于动态的调用实现了这个接口的类的方法,原则二

    FlyBehavior flyBehavior;

    QuackBehavior quackBehavior;

/**

 * 鸭子外观

 * 这个是不会变的就写在父类中,由子类来实现

 */

public void display()

{

}

/**

 * 动态的改变运行时特定行为的引用fly

 * @param flyBehavior

 * @return void

 */

public void setFly(FlyBehavior flyBehavior)

{

    this.flyBehavior = flyBehavior;

}

/**

 * 动态的改变运行时特定行为的引用quack

 * @param quackBehavior

 * @return void

 */

public void setQuack(QuackBehavior quackBehavior)

{

    this.quackBehavior = quackBehavior; 

}

public void performFly()

{

    //Duck并不亲自处理fly的行为而是会引用实现了FlyBehavior接口的对象

    flyBehavior.fly();

}

public void performQuack()

{

    //Duck并不亲自处理fly的行为而是会引用实现了quackBehavior接口的对象

    quackBehavior.quack();

}

}

两个接口FlyBehavior,QuackBehavior

?


1

2

3

4

5

6

7

8

9

package my.oschina.net.design.strategy;

//行为接口fly

public interface FlyBehavior {

    public void fly();

}

public interface QuackBehavior {

    public void quack();

}

实现这两个接口

FlyBehavior实现:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

package my.oschina.net.design.strategy;

/**

 * @author Eswin

 */

public class FlyNoWay implements FlyBehavior {

    @Override

    public void fly() {

        // TODO Auto-generated method stub

        System.out.println("I have No way to fly");

        

    }

}

public class FlyWithWings implements FlyBehavior{

    @Override

    public void fly() {

        // TODO Auto-generated method stub

        System.out.println("I can fly with wing!");    

    }

}

QuackBehavior实现:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

package my.oschina.net.design.strategy;

/**

 * @author Eswin

 */

public class Squeak implements QuackBehavior{

    @Override

    public void quack() 

    {

        // TODO Auto-generated method stub

        System.out.println("Squeak");      

    }

}

public class MuteQuack implements QuackBehavior {

        @Override

        public void quack() 

        {

            // TODO Auto-generated method stub

            System.out.println("I can not quack");  

        }

}

好了,现在我们来生成一个子类试试效果吧!

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

package my.oschina.net.design.strategy;

public class ModelDuck extends Duck{

    

    public ModelDuck()

    {

        //模型鸭现在不会飞

        flyBehavior = new FlyNoWay();

        quackBehavior = new Quack();

    }

    

    public void display()

    {

        System.out.println("I am a model duck!");

    }

    

}

来Test一下

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

package my.oschina.net.design.strategy;

public class TestModelDuck {

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        Duck ModelDuck = new ModelDuck();

        

        //默认的ModelDuck的fly与quack

        System.out.println("现在的模型鸭还不可以飞");

        ModelDuck.performFly();

        ModelDuck.performQuack();

        //现在我们来改变ModelDuck的Fly方式,注意我们可是在动态的改变哦!原则二、三

        ModelDuck.setFly(new FlyWithWings());

        

        System.out.println("现在的模型鸭可以飞了");

        ModelDuck.performFly();

        ModelDuck.performQuack();

    }

}

看看结果吧!O了!

联想      大家都玩过网游吧!我们在升级打怪买装备的时候,你的各项属性是否发生了变化?你换武器的时候算不算是动态的改变了自己的攻击行为?同样的攻击,我们可是造成了不同的伤害哦,对吧?

适用情况    1)系统中许多相关的类仅仅是行为有异;

2)系统需要能够在几种算法中快速动态的切换;

3)类中定义了多种行为 , 并且这些行为在这个类的操作中以多个条件选择语句的形式出现。

下面,我们分析Android中的动画是如何使用策略模式的。

1. 意图

定义一系列的算法,把它们一个个封装起来,并且使它们可互相替换。

策略模式使得算法可独立于使用它的客户而变化。

2. 结构图和代码

Animation不同动画的实现,主要是依靠Interpolator的不同实现而变。

时间: 2024-08-17 13:54:42

设计模式(一)The Strategy Pattern 策略模式的相关文章

Strategy pattern策略模式

在Java的集合框架中,经常需要通过构造方法传入一个比较器Comparator,或者创建比较器传入Collections的静态方法中作为方法参数,进行比较排序等,使用的是策略模式. 一.策略模式的定义 定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户. 二.策略模式体现了两个非常基本的面向对象设计原则: 封装变化的概念,找出应用中可能需要变化之处,把它独立出来,不要把那些不需要变化的代码混在一起,系统会变得更有弹性. 编程中使用接口,而不是对接口的实现.

设计模式总结篇系列:策略模式(Strategy)

前面的博文中分别介绍了Java设计模式中的创建型模式和结构型模式.从本文开始,将分别介绍设计模式中的第三大类,行为型模式.首先我们了解下分为此三大类的依据. 创建型模式:主要侧重于对象的创建过程: 结构型模式:主要侧重于处理类或对象的组合: 行为型模式:主要侧重于类或对象之间的交互以及职责分配. 首先了解下策略模式的概念:定义了多个算法,并将它们封装起来(一般的是每个算法封装成一个单独的类),让算法独立于客户端而可以单独变化. 具体可以看一下下面的例子(以计算加.减.乘为例): 1. 对加.减.

设计模式之第8章-策略模式(Java实现)

设计模式之第8章-策略模式(Java实现) “年前大酬宾了啊,现在理发冲500送300,冲1000送500了.鱼哥赶紧充钱啊,理发这事基本一个月一回,挺实惠的啊.不过话说那个理发店的老板好傻啊,冲1000才送500,不如冲两次500,这样可以送600呢.”“这只能说明你不是很笨,但是也算不上聪明.”“啊?难道我想错了?”“这是一种策略,策略,懂?他如果是冲1000送700的话你是不是很大的可能性冲500?而不是1000,但是如果这样的话,在“聪明人”,对,没错,就是你这样的人来说,冲两次500表

设计模式(一)学习----策略模式

策略设计模式:定义一组算法,将每个算法都分装起来,并使他们之间可以互换. 策略模式就是使用的面向对象思想中的继承和多态的机制 策略模式的通用类图: Context类:Strategy类,并且和Strategy类是整体和个体的关系,即聚合关系.对策略角色个体进行封装. Strategy接口:定义这个策略或算法必须有的方法和属性. ConcreteStrategy1,ConcreteStrategy2具体策略角色实现类.实现抽象策略中的方法,该类中含有具体的算法. 上图变成Java代码: 抽象的策略

设计模式实现(二)——策略模式的C++实现

一.策略模式的概念 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式. 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象.策略对象改变 context 对象的执行算法. 二.例子 (1) Strategy抽象类的实现 1 #ifndef STRATEGY_H 2 #define STRATEGY_H 3 4 class Strategy { 5 public: 6 Strate

《JavaScript设计模式与开发实践》—— 策略模式

策略模式的定义是: 定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. (1) 使用策略模式计算奖金 经过思考,我们想到了更好的办法--使用策略模式来重构代码.策略模式指的是定义一系列的算法,把它们一个个封装起来.将不变的部分和变化的部分隔开是每个设计模式的主题,策略模式也不例外,策略模式的目的就是将算法的使用与算法的实现分离开来. 一个基于策略模式的程序至少由两部分组成.第一个部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程. 第二个部分是环境类 Context,

设计模式@第25章:策略模式

第25章:策略模式 一.编写鸭子项目,具体要求如下: 有各种鸭子(比如 野鸭.北京鸭.水鸭等, 鸭子有各种行为,比如 叫.飞行等) 显示鸭子的信息 二.传统方案解决鸭子问题的分析和代码实现 传统的设计方案(类图) 代码实现-看老师演示 Duck 抽象类 package com.gjxaiou.strategy; public abstract class Duck { public Duck() { } public abstract void display();//显示鸭子信息 public

【设计模式】Java设计模式第零课之策略模式

从今天开始看<<Head First 设计模式>>,打算每学习一章都写一篇笔记,今天的第零篇希望是一个好的开端,能够善始善终.加油. 设计模式入门:策略模式(看实际的需求(情景)是什么,采用适当的策略) 设计原则零:不管当初软件设计的多好,一段时间之后总是成长和改变的,否则软件就会死亡. 设计原则一:找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起 把会变化的部分取出并封装起来,好让其他部分不会受到影响 这样代码引起的不经意后果变少,系统变得更有弹性

设计模式(四):策略模式

一.定义 策略就是算法,封装多种算法,算法之间可以互相替换.类似于,一道数学题有很多的思路和解题方法. 二.实例 推送策略: public interface IPushStrategy { bool Push(); } public class QQPush : IPushStrategy { public bool Push() { Console.WriteLine("QQ推送."); return true; } } public class EmailPush : IPush