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


      博文更新啦。这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几天,然后你自然会总结出 他的优势和缺点。




  • 相关阅读:
    Java 练习(获取两个字符串中最大相同子串)
    STM32F103 实现 简易闹钟小程序
    STM32F103 实现 LCD显示年月日时分秒星期 并可逐值修改的日期 小程序
    Docker报错之“Failed to get D-Bus connection: Operation not permitted”
    数据结构解析
    每天一条DB2命令-004
    每天一条DB2命令-003
    每天一条DB2命令-002
    ElasticSearch系列
    模块三 GO语言实战与应用-BYTES包与字节串操作(下)
  • 原文地址:https://www.cnblogs.com/IAmBetter/p/2429760.html
Copyright © 2020-2023  润新知