您的位置:首页 > 其它

设计模式---策略模式

2013-03-26 15:12 337 查看
今日在学习设计模式,深深地认识了自己的不足之处啊!!也认识到了一句话:“单纯为实现功能的代码不是好代码!”。我们必须要考虑到软件行业“多变”这个老魔头,时刻保持代码的可扩展性。为了丰富自己的羽翼,也为了能够和更多的人一起学习交流,写点东西吧!

策略模式

1、什么是策略模式?

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

2、策略模式设计原则?

2.1 封装“变化”,使易于变化的部分独立于不变的部分,以便修改“变化”时,其他部分不受影响。

2.2针对“接口”编程而非针对实现编程。针对“接口”编程就是针对“超类型”编程,这个“超类型”可以是“接口《interface》“也可以是”抽象类《abstract class》”。

2.3多用组合,少用继承。可能随着你的编程技术的成熟,你会越来越发现,继承是有弊端的,如:代码在多个子类中重复,运行时的行为不容易改变,

改变会牵一发动全身等等。 解决这个弊端的好方法之一就是使用组合。

3、如何实现策略模式?

3.1封装“变化”,针对“接口”编程
实现策略模式很简单,按照策略模式设计原则,我们应该把基类中易于变化的“东西”拿出来,这一部分封装成“接口”或者“抽象类”。那么我们所谓的“方法族”就是实现这个接口(或抽象类)的具体的类。比如,基类是某游戏中的“鸭子”类,我们知道所有鸭子都可以游泳,但不是所有鸭子都能呱呱叫,比如橡皮鸭子,他只会吱吱叫;也不是所有鸭子都能飞翔,橡皮鸭子就不会飞。又如,在游戏中,我们通常要加入魔幻场景,比如让鸭子借助火箭力量飞起来等。显然要用继承实现不是最好的。我们应该抽象出“飞”的行为,FlyBehavior,这个接口提供一个fly()方法。让那些飞,不会飞,借助火箭飞等等这些方法作为具体类族来实现这个接口。同理,“叫”(QuackBehavior)也是如此。这里就会有人问了,类不是对现实世界的抽象吗?不是把某个“东西”抽象吗?怎么方法也抽象出类了?对了!你说的没错,只不过,在这的这个“东西”就是个行为。

3.2利用组合

我们把变化的部分从基类中拿出来了,怎么把它放回去呢?——组合!在鸭子类这个基类中,添加一个FlyBehavior的对象,同理还有QuackBehavior的对象。这样,每个鸭子类的子类就都具有了FlyBehavior和QuackBehavior的对象。我们再给基类鸭子类中添加flyBehavior和quackBehavior的setter方法,以便可以运行时动态设置flyBehavior和quackBehavior。

4、策略模式类图

每次在着手写代码前画好类图是一个非常好的编程习惯。

先来看一下通用的策略模式类图:



在这里,Strategy就是接口,它定义了一个方法AlgorithmInterface,ConcreteStrageA,ConcreteStrageB,ConcreteStrageC都是具体的策略,要实习这个AlgorithmInterface方法。Context就是我们的基类,他要维护一个Strategy的对象。将来在写客户调用代码时,就可以根据需要来初始化这个Strategy的对象了。

下面我们来看一下刚才跟鸭子有关系的小游戏的类图



5、实现代码:

//定义飞行方法族

public interface FlyBehavior
{
void fly();
}

public class FlyWithWings:FlyBehavior
{
public void fly()
{
Console.WriteLine("我有翅膀,可以飞翔");
}
}
class FlyWithRocketPower:FlyBehavior
{
public void fly()
{
Console.WriteLine("我可以借助火箭的力量飞翔");
}
}
public class FlyNoWay:FlyBehavior
{
public void fly()
{
Console.WriteLine("我不会飞!");
}
}


//定义“叫”方法族
public interface QuackBehavior
{
void quack();
}
public class MuteQuack:QuackBehavior
{
public void quack()
{
Console.WriteLine("我不会叫!");
}
}
public class Quack:QuackBehavior
{
public void quack()
{
Console.WriteLine("我会呱呱叫!");
}
}
public class Quack:QuackBehavior
{
public void quack()
{
Console.WriteLine("我会呱呱叫!");
}
}


//鸭子基类
public class Duck
{
public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;

public void swim()
{
Console.WriteLine("我会游泳");
}
public virtual void display()
{

}

public void performFly()
{
this.flyBehavior.fly();
}
public void performQuack()
{
this.quackBehavior.quack();
}

public void setFlybehavior(FlyBehavior fly)
{
this.flyBehavior = fly;
}
public void setQuackbehavior(QuackBehavior quack)
{
this.quackBehavior = quack;
}
}
//诱饵鸭
public class DecoyDuck:Duck
{
public DecoyDuck()
{
this.flyBehavior = new FlyNoWay();
this.quackBehavior = new Quack();
}

public override void display()
{
Console.WriteLine("我是诱饵鸭!");
}
}
//橡皮鸭
public class RubberDuck:Duck
{
public override void display()
{
Console.WriteLine("我是橡皮鸭");
}

public RubberDuck()
{
this.flyBehavior = new FlyNoWay();
this.quackBehavior = new Squeak();
}
}
//红头鸭
public class RedheadDuck:Duck
{
public override void display()
{
Console.WriteLine("我是红头鸭!");
}

public RedheadDuck()
{
this.flyBehavior = new FlyWithWings();
this.quackBehavior = new Quack();
}
}
//绿头鸭
public class MallardDuck:Duck
{
public override void display()
{
Console.WriteLine("我是绿头鸭!");
}
public MallardDuck()
{
this.flyBehavior = new FlyWithWings();
this.quackBehavior = new Quack();
}
}


//测试代码
class Program
{
static void Main(string[] args)
{
Duck redduck = new RedheadDuck();
redduck.performFly();
redduck.performQuack();

redduck.setFlybehavior(new FlyWithRocketPower());
redduck.performFly();
Console.ReadKey();
}
}


关于策略模式一书《HEAD FIRST》中的动作冒险游戏代码可以给我发邮件(13623215228@163.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: