策略模式

来源:互联网 发布:修改mac地址的软件 编辑:程序博客网 时间:2024/06/05 09:24

初读《Head First》,自己的小记录。因为最近开始用c#,所以代码也用c#表示吧。(我知道写的很烂,但是我强迫自己要稍微写一下。。所以我才能真的认真看,并稍微有点思考的样子尴尬

首先是一个有关鸭子的系统。

Duck是鸭子的抽象类,MallardDuck,RedheadDuck是两种鸭子的具体类。他们都会quack和swim。

public abstract class Duck{public abstract void display ();public void quack(){Debug.Log ("quack");}public void swim(){Debug.Log ("swim");}}public class MallardDuck : Duck{public override void display(){Debug.Log("MallardDuck display");}}public class RedheadDuck : Duck{public override void display(){Debug.Log("RedheadDuck display");}}



接着,鸭子里需要添加新成员橡皮鸭。

添加完橡皮鸭后,需要同display一样重载quack(因为叫声不一样

似乎这样就可以暂时解决了。


但是当我们想给鸭子添加fly行为时,又要对橡皮鸭的fly特殊处理(因为他没法飞

于是发现了, 鸭子的行为经常产生变化,且容易引起代码的修改。

所以,我们希望将变化的部分单独拆开来,这样需要改变时,我们可以很轻易的修改或者扩充。这样不用管稳定的部分,减少我们的工作量。


将fly和quack行为单独封装出来。

每个具体鸭子都拥有 fly和quack行为接口,并且具体鸭子类可以在运行时指定具体行为。

同时我们为Duck添加 setBehavior的功能,以便更灵活的动态改变行为。

public abstract class Duck{public QuackBehavior quackBehavior;public FlyBehavior flyBehavior;public void performQuack(){quackBehavior.quack ();}public void performFly(){flyBehavior.fly();}public void setFlyBehavior(FlyBehavior fb){flyBehavior = fb;}public void setQuackBehavior(QuackBehavior qb){quackBehavior = qb;}public abstract void display ();}public interface FlyBehavior{void fly();}public class FlyWithWings{public void fly(){Debug.Log ("FlyWithWingss");}}public class FlyNoWay{public void fly(){Debug.Log ("FlyNoWay");}}public interface QuackBehavior{void quack();}public class Quack : QuackBehavior{public void quack(){Debug.Log("gugu~~");}}public class Squack : QuackBehavior{public void quack(){Debug.Log("zhizhi");}}public class MuteQuack : QuackBehavior{public void quack(){Debug.Log("Mute Quack");}}public class MallardDuck : Duck{public MallardDuck(){flyBehavior = new FlyWithWings ();quackBehavior = new Quack ();}public override void display(){Debug.Log("MallardDuck display");}}public class RedheadDuck : Duck{public override void display(){Debug.Log("RedheadDuck display");}}



设计原则:

1.封装变化

如果发现每次新的需求依赖。都会使某方面的代码发生改变,那么可以确定,这部分的代码需要被取出来,和其他稳定的代码有所区分。(例子中取出了鸭子的行为,并用封装为行为接口)


2.多用组合(有一个),少用继承(是一个)

本例中,如果将鸭子的行为使用继承 赋予 鸭子具体类的话, 那么被继承的行为就固定下来了, 无法动态改变(可以看做是针对实现编程,失去灵活性)

而实际上,本例采用组合的方式,即鸭子类拥有 行为的接口实例, 并且鸭子拥有了“运行时动态改变行为”的可能性。

所以组合带给我们的好处应该是:灵活,动态改变


3.针对接口编程,而不是针对实现编程

针对实现编程: Dog d = new Dog;
针对接口/超类型编程: Animal animal = new Dog();

针对超类型编程,可以动态的改变行为(animal)


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





0 0
原创粉丝点击