Java 设计模式:装饰器模式

装饰器模式(Decorator Pattern)

概述

所属:结构型模式,作为现有的类的一个包装。

适用时机:扩展某个类的时候。不使用子类继承的方式,避免继承带来的子类膨胀。

优点:

  • 不改变原来类的结构。
  • 与原来类解耦合。

实现

原本接口 interface A,有许多实现类,比如 class A1、class A2。为了拓展 A1、A2 的功能,需要准备一个抽象装饰类 abstract class ADecorator,封装原本接口 interface A(这里就需要将 A 作为 ADecorator 的实例变量,这样 ADecorator 的实现类就可以调用 A 原本的方法)。通过实现抽象装饰类 ADecorator ,来扩展功能。

示例代码如下:

public interface A {
    void call();
}

public class A1 implements A {
    @Override
    public void call() {
        System.out.println("I'm A1.");
    }
}

public class A2 implements A {
    @Override
    public void call() {
        System.out.println("I'm A2.");
    }
}

现在我们首先需要一个抽象装饰类 ADecorator 来封装 A,然后在 ADecorator 的具体实现类 ExtenedADecorator 中扩展其功能:

public abstract class ADecorator implements A {
    protected A decoratedA;

    public ADecorator(A decoratedA){
        this.decoratedA = decoratedA;
    }

    public void call(){
        decoratedA.call();
    }  
}

public class ExtenedADecorator extends ADecorator {

    public ExtenedADecorator(A decoratedA) {
        super(decoratedA);     
    }

    @Override
    public void call() {
        // 在这里拓展,可以直接写在该方法中,这里的扩展示例为调用 extendedMethod(decoratedA);
        decoratedA.call();
	extendedMethod(decoratedA);
    }

    private void extendedMethod(A decoratedA){
        System.out.println("I'm extendedMethod.");
    }
}

那么我们就可以对原来的 A1、A2 进行装饰,调用装饰类方法:

public class DecoratorPatternDemo {
    public static void main(String[] args) {
        
        A a1 = new A1();
        A a2 = new A2();
        
        // 原本调用 call 方法
        a1.call();
        a2.call();
        
        // 使用装饰类
        // 1.装饰原本类
        ADecorator extenedA1 = new ExtenedADecorator(a1);
        ADecorator extenedA2 = new ExtenedADecorator(a1);
        // 2.调用扩展方法
        extenedA1.call();
        extenedA2.call();
        
    }
}

业界实践

在Java中,大部分集合是非线程安全的,然而,在 java.util.Colletions 中,实现了 Synchronized 相关类,装饰非线程安全的 java.util.Colletion 实现类,将其包装为线程安全的实现类。

Colletions 中,SynchronizedCollection 为抽象装饰类装饰接口 Colletion:


而对应的 Synchronized 类作为拓展类,拓展了线程安全的功能。如 SynchronizedSet:

posted @ 2022-11-24 11:57  MeYokYang  阅读(206)  评论(0)    收藏  举报