装饰者模式

意图:
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。
适用性:
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
处理那些可以撤消的职责。
当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
假设现在有个新闻列表,新闻每被阅读一次,人气值+1,并收录到RSS中
首先先定义一个新闻对象News
1 public class News 2 { 3 /// <summary> 4 /// 新闻标题 5 /// </summary> 6 private string _news_title; 7 public string news_title 8 { 9 get { return this._news_title; } 10 set { this._news_title = value; } 11 12 } 13 /// <summary> 14 /// 新闻内容 15 /// </summary> 16 private string _news_content; 17 public string news_content 18 { 19 get { return this._news_content; } 20 set { this._news_content = value; } 21 22 } 23 }
接着定义一个抽象的新闻组件对象Component_News,改组件有个取新闻的方法
1 public abstract class Component_News 2 { 3 /// <summary> 4 /// 取新闻 5 /// </summary> 6 /// <returns></returns> 7 public abstract List<News> getListOfNews(); 8 }
接着定义一个抽象的装饰者对象Decorator_News,继承自Component_News
1 public abstract class Decorator_News : Component_News 2 { 3 /// <summary> 4 /// 取新闻 5 /// </summary> 6 /// <returns></returns> 7 public override List<News> getListOfNews() 8 { 9 return this._Component_News.getListOfNews(); 10 11 } 12 private Component_News _Component_News; 13 public Decorator_News(Component_News _Component_News2) 14 { 15 this._Component_News = _Component_News2; 16 17 } 18 }
接着再分别定义人气值+1的装饰者ConcreteDecortor_AddAmount和订阅RSS的装饰者对象ConcreteDecortor_AddRss
public class ConcreteDecortor_AddAmount : Decorator_News { public string AddAmount() { //新闻人气加一 Console.WriteLine("新闻人气已经加一"); return "新闻人气已经加一"; } public ConcreteDecortor_AddAmount(Component_News _Component_News) : base(_Component_News) { } /// <summary> /// 重写父类中读取新闻的方法 /// </summary> /// <returns></returns> public override List<News> getListOfNews() { //此处加入扩展代码:新闻人气加一 AddAmount(); return base.getListOfNews(); } } public class ConcreteDecortor_AddRss : Decorator_News { /// <summary> /// 将新闻标题加入到RSS中 /// </summary> /// <returns></returns> public string AddRss() { //新闻标题已经被RSS收录 Console.WriteLine("新闻标题已经加入到RSS中"); return ""; } public ConcreteDecortor_AddRss(Component_News _Component_News) : base(_Component_News) { } /// <summary> /// 重写父类中读取新闻的方法 /// </summary> /// <returns></returns> public override List<News> getListOfNews() { //此处加入扩展代码:将新闻标题加入到RSS中 AddRss(); return base.getListOfNews(); } }
最后,我们在定义一个被装饰者对象DB_News
1 public class DB_News : Component_News 2 { 3 /// <summary> 4 /// 从数据库中取新闻 5 /// </summary> 6 /// <returns></returns> 7 public override List<News> getListOfNews() 8 { 9 List<News> _list = new List<News>(); 10 //从数据库中取得数据填充到_list 中 11 Console.WriteLine("从数据库中取得数据填充到_list 中"); 12 return _list; 13 14 } 15 }
好了,到这里装饰者模式的对象都定义好了。接着在客户端调用一下
1 static void Main(string[] args) 2 { 3 //数据库方式取新闻(被装饰者对象) 4 Component_News _Component_News = new DB_News(); 5 //对被装饰者扩展了展示新闻标题的同时增加此新闻人气的方法 6 Decorator_News _Decorator_News = new ConcreteDecortor_AddAmount(_Component_News); 7 //对被装饰者扩展了展示新闻标题的同时同时将新闻标题加入RSS中的方法 8 _Decorator_News = new ConcreteDecortor_AddRss(_Decorator_News); 9 _Decorator_News = new ConcreteDecortor_AddMiss(_Decorator_News); 10 _Decorator_News.getListOfNews(); 11 Console.ReadKey(); 12 }
输出结果:

推荐阅读:设计模式应用场景案例分析——装饰者

浙公网安备 33010602011771号