您的位置:首页 > 其它

《Head First Design Patterns》笔记一:策略模式(Strategy Pattern)

2009-01-21 14:56 676 查看
开篇
好书大多是枯燥的,特别是设计模式方面的书籍,但有没有内容丰富且语言优美吸引人的书呢?
有《head first design patterns》就是这样的一本书,
这是多么好的书啊,我对自己说:“不要抱怨没有时间啦,把抱怨的时间挤一挤就有了”

1 为什么学习设计模式
懂得抽象(abstraction),继承(inheritance),多态(polymorphism)并不代表你是一个好的软件设计书。好的软件必要条件是容易维护,容易扩展。那么怎么怎样让自己的代码更容易维护,更优美呢,很简单,看书啊,书里都前辈的智慧和经验,跃然纸上啊,不需要我们再去走弯路,看就得到,这是多大的感恩啊,感谢主。

2 什么是设计模式
什么是面向对象设计模式呢,设计模式就是一套被反复使用,经过分类编目的代码设计经验总结,使得编码可以逐渐工程化,重在经验的重用,而不只是代码重用。这本书提到12个经典模式:
the Strategy Pattern,the Observer Pattern,the Decorator Pattern,the Factory Pattern,the Singleton Pattern,the command Pattern,the Adapter and Facade Pattern,the Template Method Pattern,the Iterator and Composite Patterns,the State Pattern, the Proxy Pattern,Compound Patterns
当然后面同样总结了其他较少用的模式。

第一篇 策略模式(the Strategy Pattern)

首先是需求,我们现在要建立一个关于鸭子的模型,有红头鸭,野鸭,橡皮鸭,分析这些鸭子都会叫,会游泳(如图,随手画的,见笑),



好,这个太简单了,我来用c#几分钟搞定他,先建立一个鸭子的抽象类,具体鸭子都继承于它(注,书里作者用的是java语言,不过设计模式是跨越语言的)

using System;
namespace Strategy
{
public abstract class Duck
{
public void Quack()
{
Console.WriteLine("I am Quacking");
}
public void Swim()
{
Console.WriteLine("I am Swimming");
}
public abstract Display();
}
}


具体的鸭子继承这个就ok了

新的需求来了,现在要加入飞行,简单啊,我们只需要在duck里加上新的方法 Fly(),所有鸭子就都会飞了,哈哈,这就是面向对象的威力;但问题来了,红头鸭,野鸭都会飞,继承没问题,但橡皮鸭不会飞啊,duck父类一改,导致继承duck的橡皮鸭也会飞了,这怎么办呢?

我们可以先思考:设计原则1:把变化的部分与不变的部分分开处理。

设计原则2:针对接口编程而不是针对实现编程。

设计原则3:多用组合,少用继承

分析:1 把变化的部分分开,当我们做出改变时,就不会影响到不变的部分。animal

2 什么是针对接口和针对实现呢,我们可以举个例子,如下

Dog d = new Dog();
d.MakeSound();

IAnimal a =new Dog();
a.MakeSound();

IAnimal a=GetAnimal();
a.MakeSound();
//IAnimal 就是接口,dog就是具体实现,显然,最下面的语句灵活性最好,不管是狗还好,是猫也好,根本不用去理会,完全倚靠GetAnimal去处理


3 为什么组合好呢,因为继承来说子类会继承父类的所有属性和方法,但具体对象千变万化,所以父类的某些属性方法可能对子类毫无作用,甚至有害。使用组合的话就更加灵活,就比如这里的鸭子父类,在父类定义fly方法的话,将使得子类橡皮鸭也能飞,而建立指向接口的属性,采取组合的方法,用户灵活的定义对象。

ok,了解了这3点,我们再继续分析鸭子模型,鸭子变化的是Fly(),Quack(),(我们考虑到有些鸭子不会叫,比如木头鸭子),不变的是Swim() ,所以我们分离出Fly() 和Quack() ,然后采用组合,建立接口IFlyBehavior,IQuackBehavior,在父类里面添加2个指向接口的属性,uml图如下



最后就是代码实现啦,总共将有13个类,代码如下,(为了文章方便观看,我把部分类合在一个页面里,实际上写代码分开比较好)

接口IFlyBehavior,类FlyWithWing,FlyNoWay如下

using System;
namespace Strategy
{
public interface IFlyBehavior
{
void Fly();
}
class FlyWithWing:IFlyBehavior
{
public void Fly()
{
Console.WriteLine("I am flying with wing");
}
}
class FlyNoWay:IFlyBehavior
{
public void Fly()
{
Console.WriteLine("I can not fly");
}
}
}


接口IQuackBehavior,类Quacks,Squeak,MuteQuack如下

using System;
namespace Strategy
{
public interface IQuackBehavior
{
void Quack();
}
class Quacks:IQuackBehavior
{
public void Quack()
{
Console.WriteLine("I am quacking");
}
}

class Squeak:IQuackBehavior
{
public void Quack()
{
Console.WriteLine("I am Squeaking");
}
}

class MuteQuack:IQuackBehavior
{
public void Quack()
{
Console.WriteLine("I can not Quack");
}
}
}


类duck如下

using System;
namespace Strategy
{
public abstract class Duck
{
private IFlyBehavior flyBehavior;
public IFlyBehavior FlyBehavior
{
get
{
return flyBehavior;
}
set
{
flyBehavior = value;
}
}
private IQuackBehavior quackBehavior;
public IQuackBehavior QuackBehavior
{
get
{
return quackBehavior;
}
set
{
quackBehavior = value;
}
}
public void Swim()
{
Console.WriteLine("I am swimming");
}
public void PerformFly()
{
if (flyBehavior !=null)
flyBehavior.Fly();
}
public void PerformQuack()
{
if (quackBehavior !=null)
quackBehavior.Quack();
}
public abstract  void Display();

}
}


类RedHeadDuck,MallardDuck,RubberDuck,WoodDuck如下

using System;
namespace Strategy
{
class RedHeadDuck:Duck
{
public RedHeadDuck()
{
this.FlyBehavior = new FlyWithWing();
this.QuackBehavior = new Quacks();
}
public override void Display()
{
Console.WriteLine("I am a RedHeadDuck");
}
}
class MallardDuck:Duck
{
public MallardDuck()
{
this.FlyBehavior = new FlyWithWing();
this.QuackBehavior = new Quacks();
}
public override void Display()
{
Console.WriteLine("I am mallardDuck");
}
}
class RubberDuck:Duck
{
public RubberDuck()
{
this.FlyBehavior = new FlyNoWay();
this.QuackBehavior = new Squeak();
}
public override void Display()
{
Console.WriteLine("i am a rubberDuck");
}
}
class WoodDuck:Duck
{
public WoodDuck()
{
this.FlyBehavior = new FlyNoWay();
this.QuackBehavior = new MuteQuack();
}
public override  void    Display()
{
Console .WriteLine ("I am a woodduck");

}
}
}


测试代码

using System;
namespace Strategy
{
class Program
{
static void Main(string[] args)
{
Duck d = new RedHeadDuck();
d.Display();
d.PerformFly();
d = new RubberDuck();
d.Display();
d.PerformQuack();
d.PerformFly();
Console.ReadLine();
}
}
}


测试结果



总结:什么是策略模式呢,就如这个鸭子例子把几种飞行动作封装到1个接口IFlyBehavior,几种叫声也封装到1个接口IQuackBehavior,策略模式就是把几种算法封装起来,客户可以随时灵活选择使用那种算法,算法本身是独立于客户的

下一篇:《Head First Design Patterns》笔记二:观察者模式(Observer Pattern)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: