java进阶系列之装饰器模式
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进阶系列之装饰器模式的更多相关文章
- Java设计模式12:装饰器模式
		
装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...
 - Java IO流以及装饰器模式在其上的运用
		
流概述 Java中,流是一种有序的字节序列,可以有任意的长度.从应用流向目的地称为输出流,从目的地流向应用称为输入流. Java的流族谱 Java的 java.io 包中囊括了整个流的家族,输出流和输 ...
 - 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
		
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...
 - Java设计模式系列之装饰者模式
		
装饰者模式的定义 动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰者模式的UML类图 一般来说装饰者模式有下面几个参与者: Component:装饰者和被装饰者共同 ...
 - 设计模式总结篇系列:装饰器模式(Decorator)
		
在面向对象设计过程中,经常会遇到需要对现有的类的功能进行扩展,通常我们可以采用继承的方式.例如老罗最近在做手机,一开始需要定义手机所应具有的功能: interface Phone{ public vo ...
 - Java设计模式系列-装饰器模式
		
原创文章,转载请标注出处:<Java设计模式系列-装饰器模式> 一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是 ...
 - Java设计模式之装饰器模式
		
1.装饰器模式的定义(保持接口,扩展功能) Decorate装饰器,顾名思义,就是动态的给一个对象添加一些额外的职责,就好比对房子进行装修一样. 2.装饰器模式的特征 具有一个装饰对象. 必须拥有与被 ...
 - (十)装饰器模式详解(与IO不解的情缘)
		
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. LZ到目前已经写了九个设计模 ...
 - 涉及模式之    装饰器模式详解(与IO不解的情缘)
		
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. LZ到目前已经写了九个设计模 ...
 
随机推荐
- 关于Python课程的一些思考。
			
出于对网络爬虫的好奇,我选修了Python程序设计,至于pyhton还能干啥还不太清除,只觉得爬一些数据很有意思,所以希望老师讲一些数据分析之类的技术.学完课程希望能分析一些数据,比如:还有: 上课的 ...
 - LayaAir疑难杂症之三:1.7版本click()、execCommand('copy')函数不生效
			
问题描述 在使用Laya1.7引擎开发H5游戏时,引入Js原生函数click( ),模拟一次点击事件,发现无效.在使用Laya1.7引擎开发H5游戏时,引入Js原生函数execCommand('cop ...
 - QPixmap 在非QtCreator环境下无法显示jpg图片
			
这几天需要实现在Qt界面中显示jpg图片,于是直接将路径传给QPixmap对象,发现显示不出来. 然而在Qt SDK自带的Demo中却可以正确显示jpg图片,经搜索引擎查找发现,是自己的exe文件缺少 ...
 - Ceph 集群整体迁移方案(转)
			
场景介绍:在我们的IDC中,存在着运行了3-6年的Ceph集群的服务器,这些服务器性能和容量等都已经无法满足当前业务的需求,在购入一批高性能机器后,希望将旧机器上的集群整体迁移到新机器上,当然,是保证 ...
 - 安装Python的numpy库
			
1. 检查是否有pip.exe, 如果没有,可以到 https://pypi.org/project/pip/#files下载 2. 安装好pip后,在安装numpy之前,查看是否安装成功,pip - ...
 - Sql Server数据库之存储过程
			
阅读目录 一:存储过程概述 二:存储过程分类 三:创建存储过程 1.创建无参存储过程 2.修改存储过程 3.删除存储过程 4.重命名存储过程 5.创建带参数的存储过程 简单来说,存储过程就是一条或 ...
 - python2和python3关于列表推导的差别
			
看下面两个例子: python2的环境:列表中的同名变量名被替换了 >>> x = 'my precious' >>> dummy = [x for x in 'A ...
 - VS code自定义用户代码片段snippet
			
打开VS code,“文件-首选项-用户代码片段-选择新建全局代码片段文件 “ 属性介绍:prefix 就是你自定义的快捷键 body 就是你自定义的代码片段 description 就是这 ...
 - springmvc+mybatis环境搭建
			
1.spring+mybatis 环境搭建: A.配置jdbc和dbcp数据源:注意版本com.mysql.cj.jdbc.Driver B.配置sessionfactory,绑定dbcp及配置map ...
 - jquery中的 deferred之 then (二)
			
例: var def = $.Deferred(); var prs1 = def.then(function (val) { var result = val + "_123" ...