关闭

详细讲解装饰者模式和继承之间的关系和优劣(讲道理这事儿,不怕过 就怕不够)

标签: 装饰者模式Decorator装饰者模式和继承孰优孰劣
1233人阅读 评论(0) 收藏 举报
分类:

在上一个装饰者模式简单实例中,可能有的朋友会觉得:使用继承不也是可以实现的嘛,干嘛这么麻烦。具体如下:
新建一个类,继承PersonBefore,然后,在子类里面调用super.eat(),也是可以直接调用父类的方法,也没有修改父类内容实现代码。

那么,这就来说说继承和装饰者模式之间的区别,为什么选择装饰者模式,而不使用继承来实现这个需求。也就是为什么装饰者设计模式会比继承好。

先来说说继承和装饰设计模式谁先出来,那必须是先是继承先出来的。

现在有以下需求:
要实现自己的一套IO系统,实现文件的读取。没必要百分百的跟jdk的功能一模一样。

首先,有 MyReader 类//专门用于读取数据的类。
为什么会有这个类呢?
因为数据类型有很多,比如文本MyTextReader,媒体MyMediaReader,等等。就会向上提取公共方法类即MyReader,可以有如下继承关系:

MyReader//专门用于读取数据的类。
	|--MyTextReader
	|--MyMediaReader
	。。。。。。//扩展的继续继承添加

但是又考虑到效率问题,要使用缓冲来提高效率。对读方法复写,那么又有如下继承关系。

MyReader//专门用于读取数据的类。
	|--MyTextReader
		|--MyBufferTextReader
	|--MyMediaReader
		|--MyBufferMediaReader

上述的体系是可以的,OK的。但是,这个MyReader以后可能还会因为新的媒体文件而必须新增加,那么就又有如下的继承关系图。

MyReader//专门用于读取数据的类。
	|--MyTextReader
		|--MyBufferTextReader
	|--MyMediaReader
		|--MyBufferMediaReader
	|--MyDataReader
		|--MyBufferDataReader
	。。。。。。//扩展的继续继承添加


问题也就随之而来了,如果再多一个子类,又得增加一个缓冲的实现子类。虽然这个体系是可以使用的。但是,扩展性不好,体系非常臃肿复杂。
那么就要对现有的体系进行优化。
所有的缓冲子类使用的技术都是相同的,没必要都给定义一个子类。现在可以直接单独定义一个缓冲类,如下:

/**
 * 专门为别人提高效率而存在的,所以,此类在初始化的时候,把被提高效率的对象传进来。
 */
class MyBufferReader {
    MyBufferReader(MyTextReader text) {
    }

    MyBufferReader(MyMediaReader media) {
    }
}

解释:
以前是有一个数据类型的类,就弄一个这个类的子类,弄个缓冲区来提高效率,来一个弄一个;
现在是定义一个缓冲区,大家公用一个缓冲区,需要提高谁的效率,把谁传进来。这样公共方法就可以得到复用。如上代码所示。

但是,上面的类的实现,扩展性很差。只要添加了新数据类型,那么就得新添构造函数。还得继续优化。
所以,又有如下的优化。
找到所有构造函数的参数的共同类型。通过多态的形式。可以提高扩展性。

/**
 * 通过多态的形式。可以提高扩展性。
 * 现在传入的参数就可以是MyTextReader、MyMediaReader、...
 * 后期再出现新的子类,也可以接受
 */
class MyBufferReader extends MyReader {
    private MyReader r;

    MyBufferReader(MyReader r) {
    }
}

为什么要继承 MyReader ?
新定义的类的作用,就是带着缓冲技术的reader,里面定义的也是读取行为,只是功能更强的读取行为。对读行为进行了增强。那么也是可以向上提升,也有读的动作。那么也是读的一份子,实现读的接口继承MyReader也是OK的。

最后,上述的继承体系,就变成了如下体系,新体系的名字就叫作装饰者模式:

MyReader//专门用于读取数据的类。
	|--MyTextReader
	|--MyMediaReader
	|--MyDataReader
	|--MyBufferReader


装饰模式比继承要灵活。避免了继承体系臃肿。
而且降低了类于类之间的关系。(继承体系的时候,缓冲类,必须继承相应的类。现在就不需要啦,没有直接关系了。)

装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
所以装饰类和被装饰类通常是都属于一个体系中的。(可以理解为实现共同的接口,或继承一样父类)

结构上来说,由原来的继承结构,变成了现在的组合结构(我里面有你的结构)。具体怎么理解。再说吧。

装饰设计模式灵活在哪呢?
继承不要写的过多,不要以继承为主。产生子类过多,体系会显得非常臃肿。假设现在有个对象,是一年前写的,现在你新来到公司,觉得他这个类的功能不够用了。我自己写个类,把他的对象传进来,然后就可以进行加强了,当我写的功能有问题的时候,要是发现我的有问题的时候,就可以把我的注释掉,然后继续使用原来的。就如同上一次的例子里面,扩展的PersonNow的方法发生了问题,那么可以注释掉不用,继续使用PersonBefore.eat();模块功能还在。项目继续可以使用。

下面把上次的例子,做个简单的升级。
有以下四个类:
Person  共同接口,实现多态用。
PersonBefore  被装饰对象类
PersonNow 装饰类
PersonDemo   装饰模式测试类

package com.lxk.designPattern.decorator;

/**
 * 公共接口(为实现多态)
 * <p>
 * Created by lxk on 2016/11/24
 */
public interface Person {
    void eat();
}

package com.lxk.designPattern.decorator;

/**
 * 被装饰的类
 * (被增强对象)
 * <p>
 * Created by lxk on 2016/11/24
 */
public class PersonBefore implements Person {
    @Override
    public void eat() {
        System.out.println("吃饭");
    }
}

package com.lxk.designPattern.decorator;

/**
 * 装饰类
 * (要去增强目标对象的类)
 * 装饰类通常会通过构造方法接收被装饰的对象。
 * 并基于被装饰的对象的功能,提供更强的功能。
 * <p>
 * Created by lxk on 2016/11/24
 */
public class PersonNow implements Person {
    private PersonBefore p;

    PersonNow(PersonBefore p) {
        this.p = p;
    }

    @Override
    public void eat() {
        //简单扩展
        System.out.println("开胃酒");
        p.eat();
        System.out.println("甜点");
        System.out.println("来一根");
    }
}

package com.lxk.designPattern.decorator;

/**
 * 装饰设计模式:
 * 当想要对已有的对象进行功能增强时,
 * 可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。
 * 那么自定义的该类称为装饰类。
 * <p>
 * 装饰类通常会通过构造方法接收被装饰的对象。
 * 并基于被装饰的对象的功能,提供更强的功能。
 */

class PersonDemo {
    public static void main(String[] args) {
        PersonBefore p = new PersonBefore();
        //p.eat();//这个是需求1.0
        PersonNow sp = new PersonNow(p);
        sp.eat();
    }
}















3
0
查看评论

装饰设计模式和继承之间的区别

这里记录自己学习过程中的装饰设计模式。 什么是装饰设计模式: 当想要对已有的对象进行功能增强时, 可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。 那么自定义的该类称为装饰类。 装饰类通常会通过构造方法接收被装饰的对象。 并基于被装饰的对象的功能,提供更强的功能。 //共同的接...
  • wobushizhainan
  • wobushizhainan
  • 2016-12-18 16:13
  • 384

java二十三种设计模式------(一)装饰模式 装饰类VS子类继承

Decorator(装饰者模式),顾名思义,就是动态地给一个对象添加一些额外的职责,就好比为房子进行装修一样。        因此,装饰器模式具有如下的特征: 1,它必须具有一个装饰的对象。(就如美容师,如果没有对象来美容,美容师也就没有存在的意义了) ...
  • qiushi_1990
  • qiushi_1990
  • 2014-08-04 14:11
  • 1322

继承,装饰者模式和动态代理之间的区别

* 继承 被增强的对象固定的 增强的内容也是固定的 * 装饰者模式 被增强的对象是可以切换的 增强的内容是固定的 还有一种更加灵活的方式,面向切面编程(AOP) ,比装饰者模式更加灵活, 被增强的对象和增强的内容都是可以更换的.
  • qq_32101859
  • qq_32101859
  • 2016-02-24 21:14
  • 2600

装饰者模式及其应用

装饰者模式及其应用前几天看了鸿洋大神的 Android 优雅的为RecyclerView添加HeaderView和FooterView,发现装饰者模式 在某些情况下是设计得如此 优雅,现在总结如下: 什么 是装饰者模式 怎样实现装饰者模式 装饰者模式的优缺点 装饰者模式在Android中的应用 什么...
  • gdutxiaoxu
  • gdutxiaoxu
  • 2016-07-11 23:52
  • 8708

设计模式 装饰者模式 带你重回传奇世界

今天继续设计模式之旅,给大家带来装饰者模式,国际惯例,先看定义。 装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上。 先简单描述下装饰者模式发挥作用的地方,当我们设计好了一个类,我们需要给这个类添加一些辅助的功能,并且不希望改变这个类的代码,这时候就是装饰者模...
  • lmj623565791
  • lmj623565791
  • 2014-04-21 20:21
  • 17622

装饰者模式Decorator(成年程序猿必须懂得一种姿势)—咱们就侃一侃

装饰者模式是动态地将责任附加上对象上。想要扩展功能,装饰者提供有别于继承的另一种选择,它利用组合和委托在 运行时动态地给组件(被装饰者)加上新的行为。 我们看下类图,也许就会理解相关的层次结构(时间和精力有限,本文中的有关图形为网上截取的,感兴趣的博友们可以利用 一些UML工具画一画) 具体一用...
  • chenleixing
  • chenleixing
  • 2015-01-07 22:05
  • 1592

详细讲解装饰者模式和继承之间的关系和优劣(讲道理这事儿,不怕过 就怕不够)

在上一个装饰者模式简单实例中,可能有的朋友会觉得:使用继承不也是可以实现的嘛,干嘛这么麻烦。具体如下: 新建一个类,继承PersonBefore,然后,在子类里面调用super.eat(),也是可以直接调用父类的方法,也没有修改父类内容实现代码。 那么,这就来说说继承和装饰者模式之间的区别,为什么...
  • qq_27093465
  • qq_27093465
  • 2016-11-24 18:12
  • 1233

装饰者模式.继承.动态代理

对象增强的手段 * 继承 被增强的对象固定的 增强的内容也是固定的 * 装饰者模式 被增强的对象是可以切换的 增强的内容是固定的 * 动态代理(AOP) 被增强的对象可以切换:Service 增强的内容也可以切换:事务处理继承:缺点: 1. 增强的内容...
  • oz965557340
  • oz965557340
  • 2017-01-16 09:53
  • 337

不怕神一样的对手就怕猪一样的队友

“不怕神一样的对手就怕猪一样的队友”这句话现在广为流传,实际上说的就是团队重要性,一个好的团队是可以克服很多你想象不大的困难, 做出你觉得不可能成绩。            但是很多时候我们面临的不是神一样的对手,而是猪一样的队友,所以很多...
  • weizhiai12
  • weizhiai12
  • 2014-04-15 12:20
  • 1783

不怕不知道,就怕不知道

哈哈哈哈哈哈哈哈哈哈。。。。。。想知道我为什么这么高兴吗?不急,待我慢慢道来。           先说说今天讲到了什么吧。 一、十进制转换成二进制 1、整数 方法:除二取余,倒序排列,高位补零 2、...
  • Ellen5203
  • Ellen5203
  • 2018-01-03 19:23
  • 23
    老铁们,支付宝扫一扫,领红包啦!
    扫一扫,红包是你的!对,你没看错,天天都有效,可以直接保存,天天扫,天天拿。不信?搞一哈,就造啦!!!
    个人资料
    • 访问:2651649次
    • 积分:22131
    • 等级:
    • 排名:第397名
    • 原创:332篇
    • 转载:82篇
    • 译文:4篇
    • 评论:1585条
    大 师 兄 说
    • 交流群:321964905(新建)
    • 我扣扣:1181415316
    • 我邮箱:cmshome@163.com
    • 我格言:"习惯就好"坑了多少人
    • 暂时在:帝都
    • 曾工作:成都
    • 我爱好:海贼王
    • 我爱好:英雄杀
    • 我家乡:济源市
    • 我爱好:写bug
    • 求求求:有问题就留言吧
    • 为啥呢:大师兄是一直在维护的
      你觉得本博文对你有用吗 有用,那就请点赞留言。 暂时没用,也请不要踩。
    博客专栏
    最新评论