设计模式学习之装饰者模式

研究了一下装饰者模式,分享一下学习心得

在学习这个模式的时候上网查了一下相关的技术博客,大部分都只是实现但是对于这里的一些细节问题很少有去讲,一开始我也只是知道这么写会实现加强一些类的功能。为了彻底搞明白我打断点一步步调试。

首先有这样一个场景

我现在想画一幅人的画像

第一步 准备一张白纸 是空白的 

第二部步画一个脸  技术不是很好,画的有点丑

第三步 脸有点黑,加点粉底吧

第四步  带上个假发,也算像个人了

用装饰者模式的实现UML图如下:

一些代码的实现如下

package design.decorator;

/**
 * @Description  Component是定义一个对象接口,可以给这些对象动态地添加职责
 * @Author DJZ-WWS
 * @Date 2019/5/9 19:09
 */
public abstract class Component {
    public abstract void operation();
}

定义一个被装饰者

package design.decorator;

/**
 * @Description  被装饰者
 * @Author DJZ-WWS
 * @Date 2019/5/9 19:09
 */
public class ConcreteComponent extends   Component {
    @Override
    public void operation() {
        System.out.println("最原始的模样什么都没有,啊好丑");
    }
}

装饰抽象类

package design.decorator;

/**
 * @Description
 * @Author DJZ-WWS
 * @Date 2019/5/9 19:15
 */
/**
 * Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说, 是无需知道Decorator的存在的
 *
 */
public abstract class Decorator extends Component {

    protected Component component;

    public Component getComponent() {
        return component;
    }

    public void setComponent(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        if (component != null) {
            component.operation();
        }
    }

}

 

装饰者模式就是采用一个类一个加强的思想,每一个类都对应着对前者功能的叠加这里具体的实现思想最后再说,先看一下每个装饰者

装饰者A

package design.decorator;

/**
 * @Description
 * @Author DJZ-WWS
 * @Date 2019/5/9 19:16
 */
class ConcreteDecoratorA extends Decorator {

    @Override
    public void operation() {
        // 首先运行原Component的operation(),再执行本类的功能,如addedState,相当于对原Component进行了装饰
        /**
         * 在执行A的时候由于调用了super的方法   被装饰者的父类是Component  根据多肽的特性它会自己执行它自己本身的实现
         */
        super.operation();//执行被装饰者

        System.out.println("画个一般的脸吧");
    }
}

装饰者B

package design.decorator;

/**
 * @Description
 * @Author DJZ-WWS
 * @Date 2019/5/9 19:16
 */
class ConcreteDecoratorB extends Decorator {
    @Override
    public void operation() {
        super.operation();
        addedBehavior();

    }

    public void addedBehavior() {
        System.out.print(" 有点丑美化一下吧,擦点粉");
    }
}

装饰者C

package design.decorator;

/**
 * @Description
 * @Author DJZ-WWS
 * @Date 2019/5/9 19:16
 */
class ConcreteDecoratorC extends Decorator {
    @Override
    public void operation() {
        super.operation();
        System.out.println("带个假发吧,噗,终于像个人了");
    }

}

测试类

package design.decorator;

/**  装饰模式客户端调用代码,装饰的过程更像是层层包装,用前面的对象装饰后面的对象
 * @Description
 * @Author DJZ-WWS
 * @Date 2019/5/9 19:11
 */
public class DecoratorClient {
    public static void main(String[] args) {
        ConcreteComponent concreteComponent = new ConcreteComponent();
        ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA();
        ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB();
        ConcreteDecoratorC concreteDecoratorC = new ConcreteDecoratorC();


        /**
         * 这里模拟画一幅画,从最开始的什么都没有,到最后的成为一副完美的画
         * 多态:编译看父类,执行看子类
         */
        concreteDecoratorA.setComponent(concreteComponent);
        concreteDecoratorB.setComponent(concreteDecoratorA);
        concreteDecoratorC.setComponent(concreteDecoratorB);
        concreteDecoratorC.operation();
    }
}

输出的结果:

最原始的模样什么都没有,啊好丑
画个一般的脸吧
有点丑美化一下吧

擦点粉带个假发吧,噗,终于像个人了

对结果进行简单的说明

首先明确一点被装饰者是谁

       被装饰者是最先被执行的,其次是A,接着是B,接着是C.一次执行他们各自的功能,为什么出出现这个执行顺序?对此我也是在这卡了一下。断点调试了几遍。

  首先要明确,A,B,C都是继承了装饰抽象类Decorator。

在图中我们在A中装入的实例是concreteComponent,那么A里面的实例对象就是concreteComponent

同理其他三者里面装的实例对象都是他们对应得对象的实例。

重点来了,当我们走到

concreteDecoratorC.operation();这一步的时候

点进方法进去看一下:

      没错,走的c本身的方法,但是紧接着C的operation方法里面又调用了super.operation(),跟着方法走进去,来到了他的父类

       因为我们之前在C里面加入的是B的实例当走到component.operation()的 时候,根据多态的特性,执行按照具体的实现执行,这个时候会用B对象执行operation()方法,然后我们走到了B

这时候发现B原来也调用了super.operation(),同样的又来到了父类装饰抽象类

        由于之前在B里面设置的实例是A的实例对象,所以它又会被A去执行,依次类推,一直执行到顶层,所以会执行装饰者类,也就是业务最初始的样貌,没有经过任何修饰的初始状态,当他们分别执行完毕的时候,根据栈的执行顺序,后进先出,所以又会继续依次执行A,B,C。最后得到我们控制台的结果。整体的一个大概流程就是这样。

       做一个 小小的说明,这个设计模式主要考察队多态的理解,还有就是方法的栈执行顺序,对这一块也不是很了解的可以自己查一查相关的资料。简单的补充一下实现多态的三个核心点

子类继承父类,子类重写父类方法,向上转型。

当然这里的继承也可以改为实现的方式,道理是一样的。

在jdk的IO实现中我们经常见到这样一个写法

 DataInputStream in=new DataInputStream(new BufferedInputStream(new  FileInputStream("D:\\JAVAworkspace\\ProgramTest\\src\\StreamDemo.java")));

       这里的设计思想也是使用到了装饰者模式,这样经过层层包装,每一次都流相关的类进行增强。感兴趣的可以去研究一下IO流的体系。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值