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. Comparator与Comparable,自定义排序和类比较器,TreeSet对象排序

    /** * 学生类 * @author Administrator * */ public class Student { private String sno ; private String sn ...

  2. debian apache2 修改默认路径

    1.修改 /etc/apache2/sites-enable/000-default.conf 将DocumentRoot改成你的路径 2.修改 /etc/apache2/apache2.conf & ...

  3. IDEA 倒入maven项目下载很慢

    1.找到安装maven的路径 2.直接搜索settings.xml文件 <mirror> <!--This sends everything else to /public --&g ...

  4. 如何限定函数只在本cpp内有效

    1.static关键字 static void s_funName(){ return:} 2.namespace 不要给命名空间名字这样外部 也调用不了 namespace { void s_fun ...

  5. python count函数

    描述 Python count() 方法用于统计字符串里某个字符出现的次数.可选参数为在字符串搜索的开始与结束位置. 语法 count()方法语法: str.count(sub, start= 0,e ...

  6. 【C语言基础】变量

    1.什么是变量? 变量的本质就是内存中一段储存空间 2.变量为什么必须初始化? 所谓初始化就是赋值的意思 3.如何定义变量 数据类型 变量名 = 要赋的值 举例子: int i = 3:等价于 int ...

  7. LeetCode 141. Linked List Cycle 判断链表是否有环 C++/Java

    Given a linked list, determine if it has a cycle in it. To represent a cycle in the given linked lis ...

  8. oracle增加记录谁在连接你的数据库

    我们都知道在v$session 中记录着客户端的机器名称,但是没有IP , 如果记录clinet ip 呢? 有两种思路: ①    利用trigger,后面就是这种方式 ②    利用 DBMS_S ...

  9. HTTP客户端识别与Cookie机制

    HTTP识别用户的几种技巧 承载用户身份信息的HTTP首部 客户端IP地址跟踪,通过用户的IP地址对其进行识别 用户登录,用认证方式识别用户 胖URL,一种在URL中潜入识别信息的技术 cookie, ...

  10. 啊哈算法第四章第二节解救小哈Java实现

    package corejava; public class FourTwo { static int m;//(m,n)为几行几列 static int n; static int p;//(p,q ...