【详解设计模式】-装饰者模式,换个马甲我也认识你!

什么是装饰者模式

装饰者模式是GOF23中设计模式之一,属于结构型模式。

通过这种设计模式,能够动态地给一个对象添加额外的能力,同时又不改变原有对象的结构。

动态地给一个类添加额外的功能,我们想到了Java中的继承机制,通过扩展父类的方式,可以让子类拥有一些额外的功能。使用装饰者模式,同样能达到这种效果,而且不用继承,使用起来更加灵活便利。

装饰者模式代码实现

我们创建一个手机接口IPhone和实现了该接口的实现类,我们准备给手机贴个膜用来保护屏幕(这就是要追加一种额外的功能)。

1、首先创建IPhone接口及实现类RedMIPhone

public interface IPhone {
    void toCall();
}

public class RedMIPhone implements IPhone{
    public void toCall() {
        System.out.println("使用红米手机通话");
    }
}

2、我们要给手机贴膜,保护屏幕。新建一个装饰着类,这个类的功能是给手机贴个膜,要实现IPhone接口,并持有一个IPhone对象的引用(也就是成员属性)。

public class ScreenFilmDecorator implements IPhone{
    private IPhone iPhone;

    public ScreenFilmDecorator(IPhone iPhone) {
        this.iPhone = iPhone;
    }

    public void toCall() {
        padScreenFilm();
        iPhone.toCall();
    }

    private void padScreenFilm(){
        System.out.println("新手机,贴个膜保护下");
    }
}

3、新建测试类验证:

public class DecoratorMain {
    public static void main(String[] args) {
        IPhone iPhone = new RedMIPhone();
        iPhone.toCall();

        // 给手机装饰个新功能
        ScreenFilmDecorator screenFilmDecorator = new ScreenFilmDecorator(iPhone);
        screenFilmDecorator.toCall();
    }
}

4、输出结果:

使用红米手机通话
新手机,贴个膜保护下
使用红米手机通话

代码实现的要点:

  • 装饰者类要实现和目标类(也就是要装饰的类)一样的接口,这样才能保证行为的一致性。
  • 装饰者类要持有一个目标类的引用(即成员属性,而且变量类型最好是接口,面向接口编程嘛,实现松耦合),要不然我去装饰哪个。

装饰者模式使用场景分析

  1. 动态地给对象添加职责(也就是功能),而不能影响其他对象的时候。
  2. 能够撤销而不影响类的现有功能。
  3. 当使用Java继承体系去扩展子类是不可能的时,或者扩展子类会导致子类膨胀,继承体系复杂难以维护时。

在源码中的应用

1、装饰着模式在JDK源码中最典型的例子就是IO流了。我们经常在包装着各种类型的InputStream或OutputStream来组成我们需要的IO流功能。

类似下面这种包装应该经常见到

 FileInputStream inputStream = new FileInputStream(new File("a.txt"));
 BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);

2、集合框架中工具类Collections,提供了一些诸如SynchronizedXxx()的方法,获取一个线程安全的同步容器,其实在并发编程场景较少使用(我们更多会使用并发容器),其实现原理就是使用了装饰着模式,将原有的集合做了一次装饰(或者说是包装),增加了Sychronized锁的机制。

看下面源码会更清楚:

    static class SynchronizedList<E>
        extends SynchronizedCollection<E>
        implements List<E> {
        private static final long serialVersionUID = -7754090372962971524L;

        final List<E> list;

        SynchronizedList(List<E> list) {
            super(list);
            this.list = list;
        }
        SynchronizedList(List<E> list, Object mutex) {
            super(list, mutex);
            this.list = list;
        }
    ......

设计模式系列文章回顾

Java面试必备:手写单例模式

工厂模式超详解(代码示例)

设计模式之原型模式

设计模式之代理模式

设计模式之委派模式,大名鼎鼎的Spring都在用

我要打十个!详解建造者模式(builder pattern)

【详解设计模式】-策略模式

公众号:Java成魔之路
免费领资料:公众号内回复“二营长”

有帮助到的话,点赞加关注,多谢!!

你可能感兴趣的:(设计模式)