装饰者模式

   单一职责原则

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

   里氏替换原则

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

   依赖倒置原则

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

   接口隔离原则

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

   迪米特法则

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

   开闭原则

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

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

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

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

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

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

    于是我们有了下面的代码

    第一版代码如下

    

    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();
        }
    }
}

 

转载于:https://www.cnblogs.com/student-note/p/6122965.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值