装饰者模式

意图: 
动态地给一个对象添加一些额外的职责。就增加功能来说,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         }

输出结果:

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

posted @ 2015-12-05 17:20  AntColony  阅读(116)  评论(0)    收藏  举报