软件设计模式-策略模式


最近在读一本很棒的关于软件设计模式的书《HeadFirst设计模式》,这本书很有趣,用幽默的语言和图片介绍了许多设计模式,现在我刚看完第一个设计模式,来总结一下加深记忆与理解。

问题提出

假设你有一个鸭子的基类Duck,类中定义了一些鸭子的共性,并且有许多派生类,如绿头鸭,白鸭,橡皮鸭,打猎用诱饵鸭(一种木头鸭子)等等。这时客户要求实现一些鸭子的飞行方法与发出叫声的方法,你该怎么做?

1、使用继承?

将飞行方法与发出声音的方法声明为虚方法,由子类继承后再各自实现。这将会导致一个问题,橡皮鸭与打猎用诱饵鸭不会飞,打猎用诱饵鸭不会叫,他们不该有飞行或者发出声音的方法,使用继承可能会带来许多问题。

2、使用接口?

因为某些鸭子飞行或发出声音的方式不同,因此用基类来实现接口时不合适的。所以我们要为每个子类实现这些接口,假如Duck类由40几个派生类,那就得为这所有的派生类实现接口。如果一些鸭子飞行方式或发出得声音相同,就会出现大量的代码重复,为以后代码的维护与更改带来巨大的麻烦。

设计原则

1、找出代码可能会经常发生变动的部分,将其独立出来,这样改动这一部分时便不会影响到其他部分。
2、针对接口编程,而不是针对实现编程,(在这里,我们将不再使用基类Duck或其派生类来实现方法或接口,而是定义一个接口,创建新的类来实现他,这些类称为行为类,等下我们就可以看到这种设计的灵活性)。

解决方案

我们将定义两个接口,分别用于表示飞行与发出声音,然后根据鸭子们不同的飞行方式与发出的声音,设计不同的行为类,然后在鸭子类中定义两个函数,利用接口可以引用实现该接口的类的原理,为不同的鸭子设定飞行模式与发出的声音。这样的设计有继承与接口的优点,同时在一定程度上消除了两者的不足。在鸭子这个例子这样设计的优点可能不明显,但是但你碰到需要根据不同情况设定对象行为的情况时,这中设计就会非常有用。
Duck类:

 abstract class Duck
    {
        protected IFly m_flyBehavior;	//Fly接口的变量
        protected IMakeSound m_makeSoundBehavior;	//MakeSound接口的变量
        //上面两个接口很关键,就是因为他们才实现了行为的任意切换
        public Duck() { }
        public abstract void Display();
        public void PerformFly()	//输出飞行内容
        {
            m_flyBehavior.Fly();
        }
        public void PerformMakeSound()	//输出发出的声音的内容
        {
            m_makeSoundBehavior.MakeSound();
        }
        public void Swim()
        {
            Console.WriteLine("I am swimming");
        }
        public void SetFlyBehavior(IFly fly)	//设定飞行模式
        {
            this.m_flyBehavior = fly;
        }
        public void SetMakeSoundBehavior(IMakeSound makeSound)	//设定发出的声音
        {
            this.m_makeSoundBehavior = makeSound;
        }

两个接口:

//飞行接口
 interface IFly
{
    void Fly();
}

//发出声音的接口
interface IMakeSound
{
    void MakeSound();
}

行为类:

//用翅膀飞行的鸭子
class FlyWithWings:IFly
{
    void IFly.Fly()
    {
        Console.WriteLine("I am flying with wings");
    }
}

//不会飞的鸭子
class NotFly:IFly
{
    void IFly.Fly()
    {
        Console.WriteLine("I can not fly");
    }
}

//给鸭子装火箭(笑。。)
class FlyWithRocket:IFly
{
    void IFly.Fly()
    {
        Console.WriteLine("I am flying with a rocket");
    }
}

//橡皮鸭的声音
class RubberDuckSound:IMakeSound
{
    void IMakeSound.MakeSound()
    {
        Console.WriteLine("吱吱吱");
    }
}

//木头鸭的声音
class WoodDuckSound:IMakeSound
{
    void IMakeSound.MakeSound()
    {
        Console.WriteLine("I can not make sound");
    }
}

//真鸭子的声音
class RealDuckSounds:IMakeSound
{
    void IMakeSound.MakeSound()
    {
        Console.WriteLine("嘎嘎嘎");
    }
}

//开心的鸭子的声音(我编的)
class HappyDuck:IMakeSound
{
    void IMakeSound.MakeSound()
    {
        Console.WriteLine("哈哈哈");
    }
}

测试:

ModelDuck modelDuck = new ModelDuck();	//创建一只橡皮鸭
modelDuck.SetFlyBehavior(new NotFly());		//设定飞行模式为不会飞
modelDuck.SetMakeSoundBehavior(new RubberDuckSound());	//设定声音为吱吱吱
modelDuck.PerformFly();
modelDuck.PerformMakeSound();
modelDuck.SetFlyBehavior(new FlyWithRocket());	//给橡皮鸭装火箭
modelDuck.SetMakeSoundBehavior(new HappyDuck());	//鸭子开心了
modelDuck.PerformFly();
modelDuck.PerformMakeSound();

结果如下:在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值