当系统需要新的功能的时候,一般都是向旧的类中添加新的代码。比如一个人这个类,需要新增穿衣的功能,那么就会在人这个类中去添加对应的穿衣方法代码,用来增强人这个类的行为功能。但是这样做,会因为新加入的字段、方法等逻辑代码,导致原有 人 这个类变得复杂,新加入的穿衣功能并非 人  这个类的核心功能,穿衣只是某种情况下的特定功能,会与类中人的核心功能【比如吃饭】代码糅杂在一起。

  装饰模式,把要装饰的功能(穿衣)放在一个单独的类中,并让这个类包含他需要装饰的对象(人),当需要执行特定穿衣功能的时候,客户端灵活去装饰主类对象。这样可以使得主类(人)代码简洁,不会变的越来越复杂,使得主类 的核心功能 与    不断增加的 特定功能 分开,也能去重相关装饰逻辑,做到复用。

下面写一个例子:

创建人 类作为主类:

public class Person {

    //人的 核心功能  吃喝拉撒
    public void eat() {
        System.out.println("人的核心功能:吃喝拉撒");
    }

    //穿衣功能  新增
    public void show() {
        System.out.println("====完成穿衣");
    }
}

创建装饰抽象类:

 * @description :装饰抽象类
 */
public abstract class Decorate extends Person {

    //Decorate extends Person
    //Person是被装饰者,  Decorate是装饰者,两者有共同的父类,这里简化了用继承来表示这种关系。目的是表明二者为同一类型,二者本身行为属性没有任何逻辑上的继承关系

    //被装饰对象   人      类
    private Person person;

    //装饰操作方法,为了让子类调用,不能为private
    public void decorate(Person person) {
        this.person = person;
    }

    //装饰行为效果
    @Override
    public void show() {
        if(person != null) {
            person.show();
        }
    }

}

创建三个装饰类,继承上面的装饰抽象类,来实现具体的装饰过程效果:

 * @description :女仆装装饰类
 */
public class Nvzhuang extends Decorate {

    @Override
    public void show() {
        System.out.println("穿女仆装");
        super.show();
    }

}

 * @description :裤子装饰类
 */
public class Kuzi extends Decorate {
    @Override
    public void show() {
        System.out.println("穿裤子");
        super.show();
    }

}

 * @description :马甲装饰类
 */
public class Majia extends Decorate {
    @Override
    public void show() {
        System.out.println("穿马甲");
        super.show();
    }

}

测试主类:

 */
public class Main {

    public static void main(String[] args) {

        Person xiaomingPerson = new Person();//创建被装饰对象,小明

        Nvzhuang nvzhuang  = new Nvzhuang();//女装 装饰类
        Majia majia  = new Majia();//马甲装饰类
        Kuzi kuzi = new Kuzi();//裤子装饰类

        //如何装饰?随便自定义顺序
        nvzhuang.decorate(xiaomingPerson);// 把下面定义的穿衣装饰顺序 套到  目标对象上
        majia.decorate(nvzhuang);//先穿马甲,再穿女装
        kuzi.decorate(majia);  //先穿裤子,再穿马甲
        kuzi.show();

    }

}

效果:

穿裤子
穿马甲
穿女仆装
====完成穿衣

注意: 代码中的装饰顺序是 女仆装、马甲,裤子, 运行效果却是 裤子、马甲、女仆装 ,顺序是反过来的,这其实就是在

nvzhuang.decorate(xiaomingPerson);// 把下面定义的穿衣装饰顺序 套到 目标对象上
majia.decorate(nvzhuang);//先穿马甲,再穿女装
kuzi.decorate(majia); //先穿裤子,再穿马甲

代码进行层层递进,最终到达裤子的时候,调用

 kuzi.show();开始进行装饰,裤子装饰完成后会调用上一层的装饰对象的装饰方法进行装饰。依次往回递进。

======================================

num05---装饰模式的更多相关文章

  1. 设计模式--装饰模式Decorate(结构型)

    一.装饰模式 动态地给一个对象添加额外的职责.就增加功能来说,装饰模式相比生成子类更为灵活.有时我们希望给某个对象而不是整个类添加一些功能. 二.UML图 1.Component(概念中提到的对象接口 ...

  2. Objective-C 装饰模式--简单介绍和使用

    装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 比如游戏机有一个GamePad类, 现在要增加一个作弊功能(例如100 ...

  3. C#设计模式系列:装饰模式(Decorator)

    1. 装饰模式简介 装饰模式动态地给一个对象添加额外的职责.例如一幅画有没有画框都可以挂在墙上,画就是被装饰者.但是通常都是有画框的.在挂在墙上之前,画可以被蒙上玻璃,装到框子里,所以在画上加一层画框 ...

  4. 装饰模式 - Decorator 和 外观模式 - Facade

    装饰模式 Decorator,不改变接口但动态给对象加入责任,所需功能按顺序串联起来控制,比生成子类灵活. 外观模式 Facade,让接口更简单.为子系统中的一组接口提供一个一致的界面. 参考:

  5. php实现设计模式之 装饰模式

    <?php /* * 装饰模式:在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. * * 角色 * 抽象构件(Compone ...

  6. [工作中的设计模式]装饰模式decorator

    一.模式解析 装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式的要点主要是: 1.需要对已有对象扩展新的功能,又不希望改变原有对 ...

  7. 基于东北F4的设计模式情景剧——第一幕 装饰模式(Decorator Pattern)

    第一场 难题未解 布景:铁岭,晴天,午后,风.在一幢还算气派的写字楼的三层外墙上,挂着一条红色横幅,上面用歪歪扭扭的毛笔字写着"东北F4软件外包工作室".大风中,那早已褪色的条幅剧 ...

  8. 基础笔记10(IO 1.7try-with-resource) 装饰模式

    1.读写的类型分为字节流和字符流,字节流一般是视频音频其他所有的类型都可以. (非文档文件使用字符流易造成未知编码(?)错误) InputStream OutputStream 抽象类 fileInp ...

  9. C++设计模式-Decorator装饰模式

    Decorator装饰模式作用:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活. UML图如下: Component是定义一个对象接口,可以给这些对象动态地添加职责. ...

  10. 装饰模式(Decorator pattern)

    装饰模式(Decorator pattern): 又名包装模式(Wrapper pattern), 它以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式以对客户透明的方式动态的给 ...

随机推荐

  1. Class 'org.apache.tomcat.jdbc.pool.DataSource' not found

    把项目移动到新的运行环境时,明明包都导入了,项目也放进tomcat里面了,但是还会找不到该类 解决方法:项目右键选择底下的Properties ->project facets ->jav ...

  2. 《C++Primer》第五版习题答案--第三章【学习笔记】

    [C++Primer]第五版[学习笔记]习题解答第三章 ps:答案是个人在学习过程中书写,可能存在错漏之处,仅作参考. 作者:cosefy Date: 2020/1/10 第三章:字符串,向量和数组 ...

  3. C#调用Matlab生成的Dll

    问题描述:最近开发需要调用matlab生成的DLL,在New MWNumericArray 对象的时候报错,提示未将对象引用到对象的实例. 问题分析:因为MWArray.dll是Matlab提供的DL ...

  4. jav设计模之的动态代理

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  5. 测试工具Fiddler(一)—— 基础知识

    Fiddler基础知识 一.Fiddler是什么? Fiddler是一个http协议调试代理工具,它能够记录客户端和服务器之间的所有 HTTP请求,可以针对特定的HTTP请求,分析请求数据.设置断点. ...

  6. 一次jvm调优过程

    jvm调优实战 前端时间把公司的一个分布式定时调度的系统弄上了容器云,部署在kubernetes,在容器运行的动不动就出现问题,特别容易jvm溢出,导致程序不可用,终端无法进入,日志一直在刷错误,ku ...

  7. Python的Excel操作及数据可视化

    Excel表操作 python操作excel主要用到xlrd和xlwt这两个库,即xlrd是读excel,xlwt是写excel的库. 安装xlrd pip install xlrd 简单的表格读取 ...

  8. java集合与数组之间转换

    数组转换为集合 采用java中集合自带的asList()方法就可以完成转换了 String[] array = new String[] {"zhu", "wen&quo ...

  9. window和 linux 在一起 ios和 android在一起 net和js在一起

    step 1: Windows 10 的 Linux Bash 支持「并不是使用虚拟机/模拟器」实现的,而是嵌入一个完整的 Ubuntu Linux 环境.技术上是实时将 Linux 的系统调用转换为 ...

  10. NOI3.1 6377:生日相同 2.0

    描述 在一个有180人的大班级中,存在两个人生日相同的概率非常大,现给出每个学生的名字,出生月日.试找出所有生日相同的学生. 输入 第一行为整数n,表示有n个学生,n ≤ 180.此后每行包含一个字符 ...