zoukankan      html  css  js  c++  java
  • 装饰者模式

       单一职责原则

        定义:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。 

       里氏替换原则

        定义:所有引用基类的地方必须能透明地使用其子类的对象。

       依赖倒置原则

        定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。

       接口隔离原则

        定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。 

       迪米特法则

        定义:一个对象应该对其他对象保持最少的了解。

       开闭原则

        定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

      定义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰者模式比生成之类更为灵活

        根据定义我们可以知道装饰者模式的用处,也就是动态的添加职责

          就比如说,我开了一家星巴克,刚开始的时候只有一种咖啡,但是后来客户多了,所有样式也多了,客户的要求也多了

            刚开始的时候,客户只是点了一杯咖啡,当然好收钱,但是后面有的客户点了,双份拿铁,加珍珠,加奶.........

            在现实生活中,你肯定会想,这个好办啊,我一样一样的记下来然后根据每一样的价格求一个总和,

        于是我们有了下面的代码

        第一版代码如下

        

        abstract class yingniao//饮料基类
        {
            public virtual string Name{get;set;}
            public abstract int Money();
        }
        abstract class Decotro//配料基类
        {
           public virtual string Name{get;set;}
            public abstract int Money();
        }
        class Nai:Decotro
        {
            public Nai()
            {
                this.Name = "加奶";
            }
            public override int Money()
            {
                return 3;
            }
        }
        class zhengzhu : Decotro
        {
            public zhengzhu()
            {
                this.Name = "珍珠";
            }
            public override int Money()
            {
                return 2;
            }
        }
        
        class Coffe:yingniao
        {
            public Coffe()
            {
                this.Name = "咖啡";
            }
            public override int Money()
            {
                return 10;
            }
        }
            static void Main(string[] args)
            {
                yingniao y = new Coffe();
                Decotro dc = new Nai();
                Decotro de = new zhengzhu();
                Console.WriteLine("一共花费:{0}",y.Money()+de.Money()+dc.Money());
    
                Console.Read();
            }

      执行结果如下:

      

      很显然上面的代码满足了我们的基本需求,可是这样写没有体现出他们之间的层次关系,也就是说,如果我一个人点了两份饮料

        一份是咖啡+珍珠,一份是奶茶+摩卡, 由于他们之间没有这种层次关系,那就有可能出现,服务员给了我一份咖啡+摩卡 ,一份奶茶+珍珠

        也就是说这里少了一个类似于服务员的职责类

      所以我们改造代码如下:

           首先因为我们不管饮料还是配料都是需要算账的!!! 所以呢,我们需要给他们添加一个抽象的夫类,因为每个实例算账的方式不一样

            比如说,饮料有大杯,小杯,还有中杯的,这个都需要在具体类来实现:

        abstract class decotor
        {
            public  double d_money=0;
            public abstract double Const();//用来算钱的
        }

      然后我们让具体的类来继承它:

        饮料夫类:代码如下

        abstract class yingniao : decotor//饮料基类
        {
            private decotor d_const = null;
            public void SetDec(decotor d)
            {
                this.d_const = d;
            }
            public virtual string Name { get; set; }
            public override double Const()
            {
                if (d_const != null)
                {
                    double i=d_const.Const();
                    d_money += i;
                    return d_money;
                }
                return this.d_money;
            }
        }

      在这个类里面 我们主要添加了一个 SetDec(decotor d)的方法,这个方法呢,也就是用来表示层次结构的,通俗的来说就是用来指明上一层

        然后我们重写了算钱的这个方法,在这个方法里面,我们主要做了两件事情,

          1.获得上一层饮料/配料的价格

          2.加上本饮料/配料的价格

        这样写我们就可以在向上遍历的时候就可以获得总金额了,--------------->总觉得这个装饰者模式,用了递归的写法

      配料的代码如下:

        abstract class Decotro : decotor//配料基类
        {
            private decotor d_const = null;
            public void SetDec(decotor d)
            {
                this.d_const = d;
            }
            public virtual string Name { get; set; }
    
            public override double Const()
            {
                if (d_const != null)
                {
                    double i = d_const.Const();
                    d_money += i;
                    return d_money;
                }
                return this.d_money;
            }
        }

       我们可以看到这里饮料和配料的类一模一样,这样就重复了,当然有些东西是可以移走的,别着急,等会在说,

      然后,我们就可以实现具体的类了,  如下:

      

        class Nai : Decotro//加奶
        {
            public Nai()
            {
                this.Name = "";
                this.d_money = 3;
            }
            public override double Const()
            {
                Console.WriteLine("加{0}............",this.Name);
                return base.Const();
            }
        }
        class zhengzhu : Decotro//珍珠
        {
            public zhengzhu()
            {
                this.Name = "珍珠";
                this.d_money = 2;
            }
            public override double Const()
            {
                Console.WriteLine("加{0}............",this.Name);
                return base.Const();
            }
        
        }

      然后是一种饮料的具体类

        class Coffe : yingniao//咖啡
        {
            public Coffe()
            {
                this.Name = "咖啡";
                this.d_money = 10;
            }
            public override double Const()
            {
                Console.WriteLine("一杯{0}......",this.Name);
                return base.Const();
            }
        }

      这样子,基本上我们就写完了,让我们来走一波------------

            static void Main(string[] args)
            {
    
                Coffe c = new Coffe();
                Nai n = new Nai();
                zhengzhu z = new zhengzhu();
                n.SetDec(c);
                z.SetDec(n);
                z.Const();
                Console.WriteLine(z.d_money);
                Console.Read();
            }

      运行效果如下:

      

        这样子,我们就实现了装饰者模式,可是我们写的这个还不够好,因为有一些重复的代码,所以我们需要重写

        首先,把饮料和/配料的基类中重复的字段和方法提取到夫类中

      

     abstract class decotor
        {
            public  double d_money=0;
            private decotor d_const = null;
            public virtual string Name { get; set; }
            public void SetDec(decotor d)
            {
                this.d_const = d;
            }
            public virtual double Const()
            {
                if (d_const != null)
                {
                    double i = d_const.Const();
                    d_money += i;
                    return d_money;
                }
                return this.d_money;
            }
        }

      然后我们发现这个中间的饮料抽象类和配料抽象类中一个字段/方法都不存在了,那是不是代表,这两个类是多余的呢?

         其实不是,在这个例子中,只是恰好我们饮料和配料计算钱的方式一样才出现这样的情况,实际中是需要有不同的实现的,

      最后修改后全部代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 装饰2016年11月13日
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                Coffe c = new Coffe();
                Nai n = new Nai();
                zhengzhu z = new zhengzhu();
                n.SetDec(c);
                z.SetDec(n);
                z.Const();
                Console.WriteLine(z.d_money);
                Console.Read();
            }
        }
        abstract class decotor
        {
            public  double d_money=0;
            private decotor d_const = null;
            public virtual string Name { get; set; }
            public void SetDec(decotor d)
            {
                this.d_const = d;
            }
            public virtual double Const()
            {
                if (d_const != null)
                {
                    double i = d_const.Const();
                    d_money += i;
                    return d_money;
                }
                return this.d_money;
            }
        }
        class Nai : decotor//加奶
        {
            public Nai()
            {
                this.Name = "";
                this.d_money = 3;
            }
            public override double Const()
            {
                Console.WriteLine("加{0}............",this.Name);
                return base.Const();
            }
        }
        class zhengzhu : decotor//珍珠
        {
            public zhengzhu()
            {
                this.Name = "珍珠";
                this.d_money = 2;
            }
            public override double Const()
            {
                Console.WriteLine("加{0}............",this.Name);
                return base.Const();
            }
        
        }
    
        class Coffe : decotor//咖啡
        {
            public Coffe()
            {
                this.Name = "咖啡";
                this.d_money = 10;
            }
            public override double Const()
            {
                Console.WriteLine("一杯{0}......",this.Name);
                return base.Const();
            }
        }
    }
    Hold on, everything is possible.
  • 相关阅读:
    XHProf的安装和使用(PHP性能测试神器)
    Visual自动添加CSS兼容前缀
    webpack9--删除冗余的CSS
    Vue 获取自定义属性的值
    webpack8--删除dist目录,压缩分离后的CSS
    webpack7--css压缩成单独的css文件
    APICloud 真机连接失败
    js 实现遮罩某一部分
    js实现选集功能
    微信小程序——wxParse使用方法
  • 原文地址:https://www.cnblogs.com/student-note/p/6122965.html
Copyright © 2011-2022 走看看