学了一招半式-策略模式(设计模式)

  博文更新啦。这2天学了一招分享出来,这招式如同 习武之人领悟了上层心法般。
  今天说的是设计模式中经常用到的“策略模式”,概念不说,也不想说,什么是概念,概念就是 让大家理解这个东西是什么意思,可是对于编程理论介绍往往没有实践来的一针见血。
  请耐心听完我说的话,很多朋友以为OOP就是理解了 继承 多态 封装 就够了,对,我承认这些是需要掌握,但是这是理论,这些理论的本质也需要掌握,比如:很多朋友以为  class A:class B,哇,这就是继承,可是 这个是继承吗?继承的本质是啥?继承的优势是什么?继承带来了什么好处?
就这个问题,我简单介绍下:
继承本质:你要从 内存机制下手,CLR的托管堆中的GC堆和LOAD堆下手,比如父类的字段在什么位置,比如方法表在什么位置,比如在调用方法的时候是调用什么父类的方法还是子类的方法,这些就是本质?
我写过一篇博文,对于这个本质说了一点:http://www.cnblogs.com/IAmBetter/archive/2012/02/22/2363485.html

可是,这是OOP吗,我说了这么一大堆,这些学完了是OOP吗,显然不是?
例子开始:
 

abstract class Dog
    {
        /// <summary>
        /// 一些狗公有的特性,跑,啃骨头就省略了
        /// </summary>
        public abstract void Singing();
    }

    class RedDog : Dog
    {
        public override void Singing()
        {
            Console.WriteLine("我是红狗,我会汪汪汪汪叫。。。");
        }

    }
    class BlackDog : Dog
    {
        public override void Singing()
        {
            Console.WriteLine("我是黑狗,我会哇哇哇哇叫。。。");
        }
    }

    class PcDog : Dog
    {
        //可是机器狗不会叫,也继承了怎么办?

    }

 



提示:对,我承认,你利用了 继承 多态 这2个OOP的思想,而且自以为用的还很好,可是问题来了,机器狗不会叫啊,但是也继承了Singing的方法必须实现这个抽象方法,怎么办?
很多朋友遇到了就会把这个 Singing方法抽象出来,比如抽象成一个接口,然后会叫的狗就实现这个接口。好嘞,修改代码。
 

interface ISinging
    {
        void Singing();
    }
    abstract class Dog
    {
        /// <summary>
        /// 一些狗公有的特性,跑,啃骨头就省略了
        /// </summary>
       
    }

    class RedDog : Dog,ISinging
    {
        public  void Singing()
        {
            Console.WriteLine("我是红狗,我会汪汪汪汪叫。。。");
        }

    }
    class BlackDog : Dog,ISinging
    {
        public  void Singing()
        {
            Console.WriteLine("我是黑狗,我会哇哇哇哇叫。。。");
        }
    }

    class PcDog : Dog
    {
        //机器狗不会叫,那么我就不实现接口

    }

 


哇,多完美,我用了接口实现了OOP的设计,可是问题来了?如果今天,我开心,我赋予 所有的狗要回飞,于是你又实现了 一个“IFly”的接口。哪天,我要让狗会跳舞,我还得实现“IDance”接口,依次下去。。。。
看代码:

interface ISinging
    {
        void Singing();
    }
    interface IFly
    {
        void Fly();
    }
    abstract class Dog
    {
        /// <summary>
        /// 一些狗公有的特性,跑,啃骨头就省略了
        /// </summary>
       
    }

    class RedDog : Dog,ISinging,IFly
    {
        public  void Singing()
        {
            Console.WriteLine("我是红狗,我会汪汪汪汪叫。。。");
        }

        public void Fly()
        {
            Console.WriteLine("我会飞");
        }

    }
    class BlackDog : Dog,ISinging,IFly
    {
        public  void Singing()
        {
            Console.WriteLine("我是黑狗,我会哇哇哇哇叫。。。");
        }
        public void Fly()
        {
            Console.WriteLine("我会飞");
        }
    }

    class PcDog : Dog,IFly
    {
        //机器狗不会叫,那么我就不实现接口
        public void Fly()
        {
            Console.WriteLine("我会飞");
        }

    }

 



对,我承认,你利用了接口是完成了客户的需求,可是如果客户是个变态,他需要100000种狗,那么你这个 Fly方法必须写100000次,好庞大的代码量。

对了,我们说过OOP实现了代码复用,为什么不考虑下能否代码复用呢?

very good 策略模式的本质出现了:把所有的方法抽象出来,类似于你的接口,然后利用复用代码的特点,节省开发,灵活改变。

有点领悟没?就是说,你的接口实现,比如一个需求来了,你是为了 完成这个需求(设计)而写代码,这是解决方法,不是思想,而OOP思想是为了 接口编程,为了N多设计,为了N多需求,从一定的高度思考设计框架的一个过程。

不说废话,开始写:
思考下:
狗Singing()方法是吧,如果有2种叫法,一种 哇哇叫,一种汪汪叫,那就抽象出来
狗还会飞()方法,比如会 低空飞,高空飞。
把这些会改变的动作抽象出来,把那些不会改变的动作封装起来,一起继承。
 

/// <summary>
    /// 这是所有Sing的叫法
    /// </summary>

    interface ISingable
    {
        void Singing();
        
    }

    class WAWA_Sing:ISingable
    {
        public void Singing()
        {
            Console.WriteLine("我会哇哇叫。。。");
        }
    }
    class wangwang_Sing : ISingable
    {
        public void Singing()
        {
            Console.WriteLine("我会汪汪叫。。。");
        }
    }


    /// <summary>
    /// 这是所有Fly的飞法
    /// </summary>
    ///

    interface IFlyable
    {
        void Fly();
    }
    class L_Fly:IFlyable
    {
        public void Fly()
        {
            Console.WriteLine("我会低空飞行");
        }
    }

    class H_Fly : IFlyable
    {
        public void Fly()
        {
            Console.WriteLine("我会高空飞行");
        }
        
    }
    abstract class Dog
    {
        /// <summary>
        /// 一些狗公有的特性,跑,啃骨头,是公有的特性不会改变,所以封装起来被继承
        /// </summary>
        ///
        protected ISingable isingable;
        protected IFlyable iflyable;


        public void PerformSing()
        {
            isingable.Singing();
        }

        public void PerformFly()
        {
            iflyable.Fly();
        }
       
    }

    class RedDog : Dog
    {
        public RedDog()
        {
            isingable = new WAWA_Sing();
            iflyable = new H_Fly();
        }

    }
    class BlackDog : Dog
    {
        public BlackDog()
        {
            isingable = new wangwang_Sing();
            iflyable = new L_Fly();
        }
    }

 


代码如上:
1.当还有900个不同的狗 要设计的时候,如何飞,如何叫,只要在这个狗的构造函数内 声明下 是什么叫法类型的对象,是什么飞行类型的对象即可---实现了复用
2.对于如果没有会飞的狗或者不会叫的狗,必须在写代码前就考虑好。


这就是策略模式。

不妨大家可以尝试着,用这个模式 遇到什么设计都用这个模式,练习10几天,然后你自然会总结出 他的优势和缺点。




posted @ 2012-04-02 11:19  Anleb  阅读(627)  评论(1编辑  收藏  举报