博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
装饰者模式
阅读量:5106 次
发布时间:2019-06-13

本文共 7082 字,大约阅读时间需要 23 分钟。

   单一职责原则

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

   里氏替换原则

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

   依赖倒置原则

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

   接口隔离原则

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

   迪米特法则

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

   开闭原则

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

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

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

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

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

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

    于是我们有了下面的代码

    第一版代码如下

    

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

你可能感兴趣的文章
一些方便系统诊断的bash函数
查看>>
jquery中ajax返回值无法传递到上层函数
查看>>
css3之transform-origin
查看>>
[转]JavaScript快速检测浏览器对CSS3特性的支持
查看>>
Master选举原理
查看>>
[ JAVA编程 ] double类型计算精度丢失问题及解决方法
查看>>
小别离
查看>>
微信小程序-发起 HTTPS 请求
查看>>
WPF动画设置1(转)
查看>>
基于node/mongo的App Docker化测试环境搭建
查看>>
java web 中base64传输的坑
查看>>
秒杀9种排序算法(JavaScript版)
查看>>
Activiti入门 -- 环境搭建和核心API简介
查看>>
struts.convention.classes.reload配置为true,tomcat启动报错
查看>>
MySQL的并行复制多线程复制MTS(Multi-Threaded Slaves)
查看>>
好玩的-记最近玩的几个经典ipad ios游戏
查看>>
MySQL更改默认的数据文档存储目录
查看>>
PyQt5--EventSender
查看>>
Sql Server 中由数字转换为指定长度的字符串
查看>>
Java 多态 虚方法
查看>>