设计模式-装饰器模式

为了给一个现有的类增加一些新的功能,而不引其原来类的修改,用装饰模式去代替继承模式,

要求装饰类和被装饰类实现同一接口,装饰对象有被装饰对象的实例。

在面向对象设计过程中,经常会遇到需要对现有的类的功能进行扩展,通常我们可以采用继承的方式。例如老罗最近在做手机,一开始需要定义手机所应具有的功能:

1interfacePhone{23publicvoidtel();45publicvoidsms();67}

在此,为简单起见,只是定义了接打电话和收发短信功能。

然后,老罗开始造手机,经过两年艰苦努力,第一代手机T1终于面世了,很高兴的开了发布会,反响还不错。

1classT1implementsPhone{23@Override4publicvoidtel() {5System.out.println("可以实现基本的接打电话");6}78@Override9publicvoidsms() {10System.out.println("可以实现基本的收发短信功能");11}1213}

T1面世了,当然,只有不短的追求才有更大的进步的,在进一步的努力后,新一代的T2可以在T1的基础上实现安装Android软件的功能了。通常情况下,我们可能进行如下定义:

1classT2extendsT1{23publicvoidinstallApk(){4System.out.println("可以安装Android软件了");5}67}

显然,采取了继承的方式,T2在T1的基础上新增了自己所具有的更多功能——可以安装Android软件。这是一个进步。

又过了一段时间,老罗想出做手机不仅仅需要满足这些基本的功能,还应该最大程度上的最好用户体验,于是,目前最快的闪拍被想到了,此功能被加入到了最新一代的T3中。

1classT3extendsT2{23publicvoidfastestPhoto(){4System.out.println("可以实现目前最快的闪拍");5}67}

自然的,我们首先想到的还是通过继承的方式,在继承第2代基础上扩充了T3的功能。

当然,这是一件相当值得庆贺的事情。现在T1、T2、T3都面向市场推出了。由于市场需求较大,每一代的手机都在不断的制造中。现在有一个新的需求出来了,电信的用户反馈,这么手机都不支持电信卡,怎么办?

于是,老罗为了满足电信用户,急需在T2上推出相应的电信手机,那么现在怎么办呢?第一个想到的可能是修改T2类:

1classT2extendsT1 {23publicvoidinstallApk() {4System.out.println("可以安装Android软件了");5}67@Override8publicvoidtel() {9supportDx();10System.out.println("可以实现基本的接打电话");11}1213@Override14publicvoidsms() {15supportDx();16System.out.println("可以实现基本的收发短信功能");17}1819publicvoidsupportDx() {20System.out.println("可以支持电信用户了");21}2223}

现在问题就出来了,由于继承关系的存在,虽然表面上只是修改了T2类,实际上其所有的子类都间接的被修改了。那么现在又有两个选择,要么修改其所有子类,这肯定不实际,要么不修改T2类,以免带来不必要的T2修改后对其所有子类的影响,但为了满足需求,可能得继承T2类新定义一个新的类,这样会导致类的无线膨胀问题(因为这种需求是不可预估的),那么有没有什么好的解决方案呢?

于是,基本包装/装饰而不是继承来实现此类场景的类的设计是一个不错的选择。由此带来的设计模式称之为"装饰模式"。

为了给一个现有的类增加一些新的功能,而不引其原来类的修改,用装饰模式去代替继承模式,要求装饰类和被装饰类实现同一接口,装饰对象有被装饰对象的实例。

那么我们具体看一下在上面场景中使用装饰模式如何设计类。

1classT2implementsPhone {23privatePhone phone;45publicT2(Phone phone) {6this.phone =phone;7}89publicvoidinstallApk() {10System.out.println("可以安装Android软件了");11}1213@Override14publicvoidtel() {15phone.tel();16}1718@Override19publicvoidsms() {20phone.tel();21}2223}

T3类设计与之类似,那么现在T2需要支持电信用户呢?这是直接修改T2类即可,并且对其他类(因为它没有子类之说了)是没有影响的。

1classT2implementsPhone {23privatePhone phone;45publicT2(Phone phone) {6this.phone =phone;7}89publicvoidinstallApk() {10System.out.println("可以安装Android软件了");11}1213@Override14publicvoidtel() {15this.supportDx();16phone.tel();17}1819@Override20publicvoidsms() {21this.supportDx();22phone.tel();23}2425publicvoidsupportDx() {26System.out.println("可以支持电信用户了");27}2829}

测试:

1publicclassDecoratorTest {23publicstaticvoidmain(String[] args) {4Phone t1 =newT1();5Phone t2 =newT2(t1);6t2.tel();7t2.sms();8}910}

怎么样,利用装饰模式设计类代替原本的继承是不是优势马上显示出来了,可能有人会说,这样设计会违背T2的愿意,可能有些T2本没必要支持电信用户,哦,确实如此,那好办啊,在创建的时候T2对象的时候加一个参数去控制就可以了啊。大概如下:

1classT2implementsPhone {23privatePhone phone;4privatebooleanisSupportDx;56publicT2(Phone phone,booleanisSupportDx) {7this.phone =phone;8this.isSupportDx =isSupportDx;9}1011publicvoidinstallApk() {12System.out.println("可以安装Android软件了");13}1415@Override16publicvoidtel() {17this.supportDx();18phone.tel();19}2021@Override22publicvoidsms() {23this.supportDx();24phone.tel();25}2627publicvoidsupportDx() {28if(isSupportDx) {29System.out.println("可以支持电信用户了");30}31}3233}

1publicclassDecoratorTest {23publicstaticvoidmain(String[] args) {4Phone t1 =newT1();5Phone t2 =newT2(t1,true);//Phone t2 = new T2(t1, false);6t2.tel();7t2.sms();8}910}

怎么样?装饰模式还是不错的吧,Java IO中的包装流都是采用装饰模式实现的哦。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容