装饰模式
来源:互联网 发布:淘宝潮男衣服店铺推荐 编辑:程序博客网 时间:2024/04/26 18:55
装饰模式
前言
国庆假期算是过完了,本来还想在家里写完设计模式的内容的,结果人算不如天算啊,没怎么学,不过呢,也没啥可惜的,我多陪陪家人也是挺好啊,喜欢和家人在一起.
今天算是再接着写点东西吧,还记得以前说过男人帮这个电视剧吗?今天我又想起来了一点,给大家说说一个场景,开场白:我们生活在这个一秒钟一个变化的世界里,有时候友情比爱情更可靠,朋友可以在你最艰苦的时候默默守候,在你一切平安的时候,云淡风轻的离开,爱人有时候相反,男人和女人的友情又不一样,男人如此粗暴而简单,女人的友情温婉而复杂,当男女的友情遇到了男女的爱情,就会迅速变成两个阵营.
我们都需要爱情,就像我们都需要有情一样,我们在这个世界上不断的寻找,因为我们缺一不可.
场景模拟
这样让我想起了我的一个好友,就是上一讲说过的老李,人家老李是有对象的人,所以他不光有友情还有爱情,不过,就在最近几天他们吵架啦,什么原因咱不得而知.总之身为男人的老李决定主动认错挽回女友,但是具体该怎么办呢?送花,写信,还是送礼物?只要有诚意,一定会成功归来的!
下面我们使用代码来实现:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; namespace 装饰模式{ class Program { static void Main(string[] args) { MrLi li = new MrLi(); //带上东西 li.Operation(); Console.Read(); } } public class MrLi { private const string name = "limou"; //道歉信 public void Letters() { Console.WriteLine("道歉信 "); } //玫瑰花 public void Rose() { Console.WriteLine("玫瑰花 "); } //女友送的围巾 public void Scarf() { Console.WriteLine("女友送的围巾 "); } //带上挽回女友的东西 public void Operation() { Console.WriteLine("带上: "); this.Letters(); this.Rose(); this.Scarf(); } }}
刚模拟完,就接到老李的电话说成功了,用这招看来挺管用啊,我说我们明晚吃饭庆祝一下吧?老李是个重色轻友的人,所以你懂得,人家明天晚上要陪女友,呵呵!
那天明天和女友约会肯定不再会是这一套了,肯定不管用了,如果他明天继续带上玫瑰花,戴上太阳镜和围巾呢?这个时候我们刚才实现的类好像不能满足了,怎么办呢?最烂的办法就是在MrLi类中加入一个带太阳镜的方法,为什么是最烂的方法呢?因为它违背了面向对象原则中的开放-封闭原则.那么什么是开放封闭原则?
开放封闭原则:类可扩展,但不可修改!
那么如何能支持MrLi的装扮可以自定义随意交换呢?不要着急,先看看装饰模式吧.
装饰模式
装饰模式:装饰模式是动态的给对象增加责任,对扩展功能来说,装饰模式提供了比继承更灵活的方案.
装饰模式类图如下:
Component类:用来抽象装饰对象与被装饰对象的共同的装饰行为.
ConcreateComponent类:是一个被装饰的主对象.
Decorator类:是一个用来装饰的抽象类,包含了Component类的实例与实现了装饰与被装饰对象的共同行为,包含Component类实例表示将来具体的装饰类都有一个明确的被装饰对象.
ConcreteDecratorA与ConcreteDecratorB类:是具体装饰类实例,该对象实现了抽象的Deccorator类,包含一个被装饰对象用来装饰此对象.
装饰模式代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; namespace 装饰模式Test{ class Program { static void Main(string[] args) { //定义被装饰对象 主装饰对象 ConcreteComponent cc = new ConcreteComponent(); //定义具体装饰对象A 主对象上的装饰 ConcreteDecoratorA cda = new ConcreteDecoratorA(); //定义具体装饰对象B 主对象上的装饰 ConcreteDecoratorB cdb = new ConcreteDecoratorB(); //装饰对象A 装扮主对象cc cda.SetComponent(cc); //装饰对象B 装扮装饰对象A cdb.SetComponent(cda); //开始装扮 cdb.Operation(); //第二种装扮 //装饰对象B 装扮主对象cc cdb.SetComponent(cc); //装饰对象A 装扮装饰对象B cda.SetComponent(cdb); //开始装扮 cda.Operation(); Console.ReadKey(); } } /// <summary> /// 装饰行为的抽象 /// </summary> public abstract class Component { //操作 public abstract void Operation(); } /// <summary> /// 被装饰的对象 /// </summary> public class ConcreteComponent : Component { public override void Operation() { Console.WriteLine("具体对象的操作"); } } /// <summary> /// 抽象的装饰类 /// </summary> public abstract class Decorator : Component { protected Component component; public void SetComponent(Component component) { this.component = component; } public override void Operation() { if (component!=null) { component.Operation(); } } } /// <summary> /// 具体的装饰类 /// </summary> public class ConcreteDecoratorA : Decorator { private void AddedBehaviorA() { Console.WriteLine("装饰A"); } public override void Operation() { base.Operation(); AddedBehaviorA(); } } public class ConcreteDecoratorB : Decorator { private void AddedBehaviorB() { Console.WriteLine("装饰B"); } public override void Operation() { base.Operation(); AddedBehaviorB(); } }}
我们看到,有了装饰模式,我们可以轻易的增加装饰对象,并且灵活的组织装饰对象装扮的顺序,那如果我们用装饰模式实现我们第一部分的场景应该如何呢?
装饰模式的灵活运用
那我们设计的类图如下:
代码实现如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; namespace 灵活运用{ class Program { static void Main(string[] args) { MrLi li = new MrLi(); //第一天道歉的打扮 Console.WriteLine("第一天道歉的打扮: "); //道歉信 Letters letters = new Letters(); //玫瑰花 Rose rose = new Rose(); //女友送的围巾 Scarf scarf = new Scarf(); //打扮道歉信 letters.SetDressUp(li); //打扮玫瑰 rose.SetDressUp(li); //打扮围巾 scarf.SetDressUp(li); //开始打扮 letters.ToDressUp(); rose.ToDressUp(); scarf.ToDressUp(); Console.WriteLine(); Console.WriteLine("------------"); //第二天约会的打扮 Console.WriteLine("第二天约会的打扮: "); //道歉信 Letters let = new Letters(); //太阳镜 Sunglasses sunglass = new Sunglasses(); //女友送的围巾 Scarf sca = new Scarf(); //打扮道歉信 let.SetDressUp(li); //打扮太阳镜 sunglass.SetDressUp(li); //打扮围巾 sca.SetDressUp(li); //开始打扮 let.ToDressUp(); sunglass.ToDressUp(); sca.ToDressUp(); Console.ReadKey(); } } /// <summary> /// 打扮的抽象类 /// </summary> public abstract class DressUp { //开始打扮 public abstract void ToDressUp(); } /// <summary> /// 被装饰的对象:老李.围巾等饰品都是装饰在身上 /// </summary> public class MrLi : DressUp { private const string name = "limou"; public override void ToDressUp() { Console.Write("{0}开始打扮如下饰品: ",name); } } /// <summary> /// 装饰品抽象类 /// </summary> public abstract class Decorator : DressUp { //实现一个被装饰对象用来记录装饰谁 protected DressUp component = null; //设置被打扮对象 public void SetDressUp(DressUp com) { this.component = com; } //默认的装扮实现 public override void ToDressUp() { if (component!=null) { component.ToDressUp(); } } } /// <summary> /// 道歉信装饰类 /// </summary> public class Letters : Decorator { //开始打扮 public override void ToDressUp() { base.ToDressUp(); Console.WriteLine("道歉信 "); } } /// <summary> /// 玫瑰花装饰类 /// </summary> public class Rose : Decorator { //开始打扮 public override void ToDressUp() { base.ToDressUp(); Console.WriteLine("玫瑰花 "); } } /// <summary> /// 围巾装饰类 /// </summary> public class Scarf : Decorator { /// <summary> /// 开始打扮 /// </summary> public override void ToDressUp() { base.ToDressUp(); Console.WriteLine("女友送的围巾 "); } } /// <summary> /// 太阳镜装饰类,可以添加需要的装饰类 /// </summary> public class Sunglasses : Decorator { /// <summary> /// 开始打扮 /// </summary> public override void ToDressUp() { base.ToDressUp(); Console.WriteLine("太阳眼镜 "); } }}
总结
这样利用装饰模式就可以有效的解决将来对新饰品的扩展而无需去修改原来的类,完全满足了开放封闭的原则.