1、介绍

装饰器模式顾名思义就是装饰某个对象的,是一种结构型模式。装饰器模式允许向一个现有对象添加新的功能,同时不改变其结构,用户可以随意的扩展原有的对象。它是作为现有的类的一个包装。装饰器模式一方面替代了继承,相对于继承带来的静态的功能扩展,装饰器模式可以理解为动态的功能扩展,非常灵活。但是由于动态扩展带来方便的同时也带来了缺点:在装饰过程中,其实创建了很多的对象占据内存资源,这些对象都很相似,排查错误也是有很大困难。

举例来说:比如有一根电线,现在只有铜丝,只不过现在只能导电,我们在他的外面加一层绝缘体比如橡胶,这样他在导电的同时还安全了,外部具有绝缘的功能。

意图:动态的给一个对象添加一些额外的职责。就增加功能来说,装饰器模式比生成子类更为灵活。

主要解决:一般的我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类也会很膨胀。

何时使用:在不想增加很多子类的情况下扩展类。

如何解决:将具体功能职责划分,同时继承装饰者模式。

应用场景:1、扩展一个类的功能;2、动态增加功能,动态撤销。

实例:装饰器模式中有一个抽象的对象,定义为接口。为何这么定义呢?这里的例子是电脑的例子,先定义一个基本的电脑,它可以是笔记本电脑,台式电脑,平板电脑等等,但是它们都有一个相同的基本信息,它们有名字,有价格。我们定义所有电脑基本的抽象方法,后期如果有新式电脑出现,新的名字,新的价格出现,最基本的是这些。

步骤1

创建一个接口。

package demo_dectorator;  

public interface AbstractComputer {
abstract String name(); //电脑名字 abstract double price(); //电脑价格
}

步骤2

创建实现接口的实体类

下面是一个对接口的实现,也是对抽象产品的具体化,这个实现可能会有很多,因为有很多品牌名字价格的电脑,这也是为何定义一个抽象类或接口的原因。假设电脑的基本价格是3000,名字是普通电脑。

package demo_dectorator;  

public class Computer implements AbstractComputer{  

    @Override
public String name() {
return "普通电脑";
} @Override
public double price() {
return 3000;
} }

步骤3

创建实现了AbstractComputer接口的抽象装饰类

下面我们对这个电脑进行改进,我们要在电脑里加内存条,增大运行内存,定义一个抽象的原件类,同样实现接口,为什么这样呢?

装饰者模式必然有一个公共的接口或者抽象类,用来作为对象的传递。你需要根据接口实现基本的被装饰类,以及装饰类的公共接口,以后所有的装饰类都是继承自公共的装饰类接口,内部实现。

在逻辑上也是可以说的过去的,电脑配件依附于电脑,拥有和电脑一样的属性。

package demo_dectorator;  

public abstract class Device implements AbstractComputer{  

    public abstract String name();  

    public abstract double price();
}

步骤4

创建扩展了Device类的实体装饰类

package demo_dectorator;  

/*内存类*/  

public class Memory extends Device{  

    public AbstractComputer computer;  

    public Memory(AbstractComputer computer) {
this.computer = computer;
} public String name() {
return computer.name() + "加内存";
} public double price() {
return computer.price() + 300;
} }
package demo_dectorator;  

/*硬盘类*/  

public class HardDisk extends Device{
public AbstractComputer computer; public HardDisk(AbstractComputer computer) {
this.computer = computer;
} public String name() {
return computer.name() + "加硬盘";
} public double price() {
return computer.price() + 500;
}
}

在装饰的过程中最重要的就是子类继承父类,在执行子类的构造方法的时候,会隐式调用super(),如下

public Memory(AbstractComputer computer) {
super();
this.computer = computer;
}
public HardDisk(AbstractComputer computer) {
super();
this.computer = computer;
}

步骤5

使用 HardDisk、Memory来装饰 AbstractComputer对象。

package demo_dectorator;  

/*
* 客户类,测试装饰器模式*/ public class Client {
public static void main(String[] args) { Computer computer = new Computer(); HardDisk h = new HardDisk(computer);
        System.out.println(h.name());
System.out.println("价格:"+h.price()); Memory m = new Memory(computer);
System.out.println(m.name());
System.out.println("价格:"+m.price()); HardDisk h1=new HardDisk(m);
System.out.println(h1.name());
System.out.println("价格:"+h1.price()); }
}

步骤6

测试输出

普通电脑加硬盘
价格:3500.0
普通电脑加内存
价格:3300.0
普通电脑加内存加硬盘
价格:3800.0

装饰器模式很好的体现开闭原则:对于扩展是开放的,对于修改是关闭的。用户可以动态添加功能。在java的io流中也是应用了装饰器模式。

java进阶系列之装饰器模式的更多相关文章

  1. Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

  2. Java IO流以及装饰器模式在其上的运用

    流概述 Java中,流是一种有序的字节序列,可以有任意的长度.从应用流向目的地称为输出流,从目的地流向应用称为输入流. Java的流族谱 Java的 java.io 包中囊括了整个流的家族,输出流和输 ...

  3. 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...

  4. Java设计模式系列之装饰者模式

    装饰者模式的定义 动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案  装饰者模式的UML类图 一般来说装饰者模式有下面几个参与者: Component:装饰者和被装饰者共同 ...

  5. 设计模式总结篇系列:装饰器模式(Decorator)

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

  6. Java设计模式系列-装饰器模式

    原创文章,转载请标注出处:<Java设计模式系列-装饰器模式> 一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是 ...

  7. Java设计模式之装饰器模式

    1.装饰器模式的定义(保持接口,扩展功能) Decorate装饰器,顾名思义,就是动态的给一个对象添加一些额外的职责,就好比对房子进行装修一样. 2.装饰器模式的特征 具有一个装饰对象. 必须拥有与被 ...

  8. (十)装饰器模式详解(与IO不解的情缘)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. LZ到目前已经写了九个设计模 ...

  9. 涉及模式之 装饰器模式详解(与IO不解的情缘)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. LZ到目前已经写了九个设计模 ...

随机推荐

  1. 关于Python课程的一些思考。

    出于对网络爬虫的好奇,我选修了Python程序设计,至于pyhton还能干啥还不太清除,只觉得爬一些数据很有意思,所以希望老师讲一些数据分析之类的技术.学完课程希望能分析一些数据,比如:还有: 上课的 ...

  2. LayaAir疑难杂症之三:1.7版本click()、execCommand('copy')函数不生效

    问题描述 在使用Laya1.7引擎开发H5游戏时,引入Js原生函数click( ),模拟一次点击事件,发现无效.在使用Laya1.7引擎开发H5游戏时,引入Js原生函数execCommand('cop ...

  3. QPixmap 在非QtCreator环境下无法显示jpg图片

    这几天需要实现在Qt界面中显示jpg图片,于是直接将路径传给QPixmap对象,发现显示不出来. 然而在Qt SDK自带的Demo中却可以正确显示jpg图片,经搜索引擎查找发现,是自己的exe文件缺少 ...

  4. Ceph 集群整体迁移方案(转)

    场景介绍:在我们的IDC中,存在着运行了3-6年的Ceph集群的服务器,这些服务器性能和容量等都已经无法满足当前业务的需求,在购入一批高性能机器后,希望将旧机器上的集群整体迁移到新机器上,当然,是保证 ...

  5. 安装Python的numpy库

    1. 检查是否有pip.exe, 如果没有,可以到 https://pypi.org/project/pip/#files下载 2. 安装好pip后,在安装numpy之前,查看是否安装成功,pip - ...

  6. Sql Server数据库之存储过程

    阅读目录 一:存储过程概述 二:存储过程分类 三:创建存储过程 1.创建无参存储过程 2.修改存储过程 3.删除存储过程 4.重命名存储过程 5.创建带参数的存储过程   简单来说,存储过程就是一条或 ...

  7. python2和python3关于列表推导的差别

    看下面两个例子: python2的环境:列表中的同名变量名被替换了 >>> x = 'my precious' >>> dummy = [x for x in 'A ...

  8. VS code自定义用户代码片段snippet

    打开VS code,“文件-首选项-用户代码片段-选择新建全局代码片段文件 “ 属性介绍:prefix   就是你自定义的快捷键 body    就是你自定义的代码片段 description 就是这 ...

  9. springmvc+mybatis环境搭建

    1.spring+mybatis 环境搭建: A.配置jdbc和dbcp数据源:注意版本com.mysql.cj.jdbc.Driver B.配置sessionfactory,绑定dbcp及配置map ...

  10. jquery中的 deferred之 then (二)

    例: var def = $.Deferred(); var prs1 = def.then(function (val) { var result = val + "_123" ...