老生常谈:装饰者模式
网站新闻模块中应用装饰模式
本人现今对设计模式特别感兴趣,因为它的功能实在是太吸引人啦.设计模式一般说来是为了增加系统的可扩展性及维护性。在一般的门户网站中都会有新闻展示这个功能模块。
具体案例:有存储在数据库中的新闻,有存储在XML文件中的新闻(一般都是推荐新闻,内容比较少)。
在没有接触设计模式时,都是针对具体实现编程,读取数据库新闻时直接写一个基于数据库的方法,读取推荐新闻时再写一个基于XML的方法,两种方法之间没有任何的关系.当时觉的这样实现也没什么不好。可是你总会发现这两种方法在实现上有很多相同的地方,都是读取出一个新闻标题集合来绑定数据源,只是取数据源的方法不同而已。为了方便管理,我们可以定义一个统一的接口来约束这两种方法。这种做法也足够满足读取不同载体的新闻要求。可是如果在读取新闻时要做其它的操作呢?例如:给读取出来的新闻的人气加一。这个时候我们就要修改原程序,这样有背于"对扩展开放,对修改关闭"的编程原则。如何解决呢?这就是装饰者模式出场的时候了。
装饰者模式 :动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
装饰者模式类图:
问题: 说装饰者模式比用继承会更富有弹性,在类图中不是一样用到了继承了吗?
说明:装饰者和被装饰者之间必须是一样的类型,也就是要有共同的超类。在这里应用继承并不是实现方法的复制,而是实现类型的匹配。因为装饰者和被装饰者是同一个类型,因此装饰者可以取代被装饰者,这样就使被装饰者拥有了装饰者独有的行为。根据装饰者模式的理念,我们可以在任何时候,实现新的装饰者增加新的行为。如果是用继承,每当需要增加新的行为时,就要修改原程序了。
说了一些装饰者模式的类图和概念,下面就要讲新闻模块和装饰者模式的关联了。
例如:在展示新闻的同时给读取出来的新闻的人气加一,同时把新闻标题加入到RSS中,如果是用继承,就要往超类中增加相应的方法,如果是一个新增行为还是可以忍受的,如果此模块有不断增加业务的可能,那是不是要每次都要修改原程序呢?我想所有的朋友都不希望这样做。我们希望当有新的行为时才往旧对象上加,是在运行时加,并不是一开始就加。
解决方案:这里我应用装饰者模式设计来满足这种不断新增业务的需求:
1:定义根据不同载体读取新闻方法的抽象类:
public abstract class Component_News
{
/**//// <summary>
/// 取新闻
/// </summary>
/// <returns></returns>
public abstract List<News> getListOfNews();
}
2:基于数据库读取新闻的类:
public class DB_News : Component_News
{
/**//// <summary>
/// 从数据库中取新闻
/// </summary>
/// <returns></returns>
public override List<News> getListOfNews()
{
List<News> _list = new List<News>();
//从数据库中取得数据填充到_list 中
Console.WriteLine("从数据库中取得数据填充到_list 中");
return _list;
}
}
3:基于XML读取新闻:
/**//// <summary>
/// 从XML中取新闻
/// </summary>
/// <returns></returns>
public override List<News> getListOfNews()
{
List<News> _list = new List<News>();
//从XML中取得数据填充到_list 中
Console.WriteLine("从XML中取得数据填充到_list 中");
return _list;
}
4:新闻实体类:
public class News
{
/**//// <summary>
/// 新闻标题
/// </summary>
private string _news_title;
public string news_title
{
get { return this._news_title; }
set { this._news_title = value; }
}
/**//// <summary>
/// 新闻内容
/// </summary>
private string _news_content;
public string news_content
{
get { return this._news_content; }
set { this._news_content = value; }
}
}
5:下面是抽象装饰类:
public abstract class Decorator_News :Component_News
{
/**//// <summary>
/// 取新闻
/// </summary>
/// <returns></returns>
public override List<News> getListOfNews()
{
return this._Component_News.getListOfNews();
}
private Component_News _Component_News;
public Decorator_News(Component_News _Component_News2)
{
this._Component_News = _Component_News2;
}
}
6:扩展新闻组件: 给新闻添加人气的方法类:
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();
}
}
7:扩展新闻组件: 把新闻加入到RSS中的方法类:
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();
}
}
8:客户端调用:为了说明问题,本人就选用控制台程序来说明.
static void Main(string[] args)
{
//数据库方式取新闻
Component_News _Component_News = new DB_News();
//扩展了展示新闻标题的同时增加此新闻人气的方法
Decorator_News _Decorator_News = new ConcreteDecortor_AddAmount(_Component_News);
//扩展了展示新闻标题的同时同时将新闻标题加入RSS中的方法
_Decorator_News = new ConcreteDecortor_AddRss(_Decorator_News);
_Decorator_News.getListOfNews();
Console.ReadKey();
}
9:运行效果:这样就可以为断的添加新的装饰者来装饰我们的新闻组件了,并不需要修改新闻组件,而只要添加新的类.Decorator模式采用对象组合大大的降低了系统的耦合度。
装饰者模式的问题及解决:用装饰者实例化组件时,将增加代码的复杂度,一旦应用了装饰者模式,不只需要实例化组件,还要把组件包装进装饰者,而这样的装饰者有多少个是不确定的。这里可以应用工厂模式来实例化组件来简化操作。
注:
本文参考:<<Head First 设计模式>>
转载于:https://www.cnblogs.com/ASPNET2008/archive/2008/06/15/1222724.html
老生常谈:装饰者模式相关推荐
- java设计模式----装饰器模式
Decorator装饰器,顾名思义,就是动态地给一个对象添加一些额外的职责,就好比为房子进行装修一样.因此,装饰器模式具有如下的特征: 它必须具有一个装饰的对象. 它必须拥有与被装饰对象相同的接口. ...
- Android 设计模式:(三)装饰者模式 —— 装饰对象
*利用组合(composition)和委托(delegation)可以在运行时实现继承行为的效果,动态地给对象加上新的行为. *利用继承扩展子类的行为,是在编译时静态决定的:利用组合的做法,可以在运行 ...
- java I/O之装饰者模式
装饰者: Decorator模式(别名Wrapper):动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案. 装饰者模式意图: 动态的给一个对象添加额外的职责.Decorato ...
- 如何利用装饰者模式在不改变原有对象的基础上扩展功能
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:双子孤狼 blog.csdn.net/zwx9001 ...
- 这是我见过最通俗易懂的 装饰者模式 讲解了!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:lewis0077 cnblogs.com/lewis007 ...
- Python设计模式-装饰器模式
Python设计模式-装饰器模式 代码基于3.5.2,代码如下; #coding:utf-8 #装饰器模式class Beverage():name = ""price = 0.0 ...
- 《JavaScript设计模式与开发实践》模式篇(12)—— 装饰者模式
在传统的面向对象语言中,给对象添加功能常常使用继承的方式,但是继承的方式并不灵活, 还会带来许多问题:一方面会导致超类和子类之间存在强耦合性,当超类改变时,子类也会随之 改变;另一方面,继承这种功能复 ...
- 3年工作必备 装饰器模式
故事 古话说的好:人靠衣裳马靠鞍.下面先带大家来熟悉这句话的背景: 人靠衣装马靠鞍,狗配铃铛跑的欢出自沈自晋<望湖亭记>第十出:"虽然如此,佛靠金装,人靠衣装,打扮也是很要紧的. ...
- 装饰者模式 php,PHP设计模式之装饰器模式
装饰器设计模式 什么是装饰器模式 装饰器模式就是对一个已有的结构增加装饰.装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象 ...
最新文章
- Check the value configured in 'zookeeper.znode.parent'
- 09_Android中ContentProvider和Sqllite混合操作,一个项目调用另外一个项目的ContentProvider
- Shell文件的排序、合并和分割
- 心理学上的被动_心理学:骨子里就被动的人,一定会有这5种表现
- leetcode 87. 扰乱字符串(dp)
- python打包成exe_python打包成exe有GUI工具啦
- 与cache相关的一些问题和思考
- LQR、LQR-MPC、GP-MPC控制倒立摆
- KindEditor上传图片word
- Android 不透明度对应数值
- ThinkPad X230 后没有了Break 以及 Pause键,网工们囧了?
- Python爬虫入门教程【11】:半次元COS图爬取
- Android实现远程控制PC(Android[客户端]+Qt[服务器端])
- 首页技术支持常见问题宽带外网IP显示为10、100、172开头,没有公网IP,如何解决?...
- 基于单片机的多功能定时器
- 算法:URL短地址压缩算法-短网址映射。
- SAP ABAP 检查物料账期函数
- 计算机原理学习(序)
- spring boot——关于一个Mysql主键的问题
- 初级JAVA程序员应该掌握的NPE知识
热门文章
- Linux复习资料——MySQL-client-5.6.50-1.el7.x86_64与MySQL-server-5.6.50-1.el7.x86_64包安装MySQL全过程
- 【蓝桥杯Java_C组·从零开始卷】第三节(附)、for循环练习题(数据题与图形题)
- 查询DBA_HIST_ACTIVE_SESS_HISTORY缓慢
- remote_os_authent参数测试!
- linux uname 命令 打印系统信息
- 来自褪墨:个人回顾与展望/2011年的回顾和对2012年的计划
- Linux软件安装之RPM的安装技巧
- 汉堡王什么汉堡好吃_315 曝光用过期面包做汉堡:汉堡王到底怎么了?
- js 链接websocket马上断开_WebSocket之基于STOMP协议的广播模式实现群聊功能
- linux定时任务_从零开始学Linux运维|41.定时任务crontab