单一职责原则
定义:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
里氏替换原则
定义:所有引用基类的地方必须能透明地使用其子类的对象。
依赖倒置原则
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
接口隔离原则
定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
迪米特法则
定义:一个对象应该对其他对象保持最少的了解。
开闭原则
定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
定义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰者模式比生成之类更为灵活
根据定义我们可以知道装饰者模式的用处,也就是动态的添加职责
就比如说,我开了一家星巴克,刚开始的时候只有一种咖啡,但是后来客户多了,所有样式也多了,客户的要求也多了
刚开始的时候,客户只是点了一杯咖啡,当然好收钱,但是后面有的客户点了,双份拿铁,加珍珠,加奶.........
在现实生活中,你肯定会想,这个好办啊,我一样一样的记下来然后根据每一样的价格求一个总和,
于是我们有了下面的代码
第一版代码如下
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(); } }}