Java设计模式之装饰器模式

来源:互联网 发布:淘宝直通车在哪开 编辑:程序博客网 时间:2024/05/18 09:25

装饰器模式

介绍

装饰器模式(Decorator Pattern)指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰类来包装原有的类,并提供额外的功能。

引入问题

举个例子,某公司拥有一众程序员。

public class Coder() {    public void code() {        System.out.println("会写代码的程序员...");    }}

现在,业务需要有Java语言code能力的程序员。按照面向对象的设计思想,一般的做法是新增一个JavaCoder类,继承Coder类

public class JavaCoder extends Coder {    public void codeJava() {        System.out.println(" 会使用Java语言....");    }}

然后,又需要有Go语言code能力的程序员,照例需要新添加一个GoCoder类,继承Coder类

public class GoCoder extends Coder {    public void codeGo() {        System.out.println(" 会使用Go语言....");    }}

这时,如果现在需要既有Java语言code能力,又有Go语言code能力的程序员,又需要创建一个JavaAndGoCoder类,这样就会导致一旦有需求增加或变更,类数量就会暴增。如果已经存在的类能复用就好了。

解决方案

装饰器模式就是为了解决上述问题而生的。它通过把复杂的功能简单化,分散化,然后在运行期间,根据需要来动态组合。装饰器模式的通用类图如下:
装饰器模式类图
在装饰器模式中一共有以下四种角色

  • Component
    增加功能时的核心角色。负责定义功能接口。
  • ConcreteComponent
    实现Component角色所定义的接口。
  • Decorator
    该角色与Component角色有相同的接口,且在该角色内保存了Component角色。
  • ConcreteDecorator
    该角色是Decorator角色的具体实现。

以上述程序员的问题为例,我们使用装饰器模式为Coder类动态添加方法

  • Coder类(扮演Component角色)
    public abstract class Coder { 
    public abstract void code();
    }
  • ConcreteCoder类(扮演ConcreteComponent角色)
    public class ConcreteCoder extends Coder { 
    @Override
    public void code() {
    System.out.println("会写代码的程序员...");
    }
    }
  • CoderDecorator类(扮演Decorator角色)
    public abstract class CoderDecorator extends Coder { 
    private Coder coder;
    public CoderDecorator(Coder coder) {
    this.coder = coder;
    }
    @Override
    public void code() {
    coder.code();
    }
    }
  • JavaCoder类(扮演ConcreteDecorator角色)
    public class JavaCoder extends CoderDecorator { 
    public JavaCoder(Coder coder) {
    super(coder);
    }
    public void codeJava() {
    System.out.println("用Java语言写代码...");
    }
    @Override
    public void code() {
    super.code();
    codeJava();
    }
    }
  • GoCoder类(扮演ConcreteDecorator角色)
    public class GoCoder extends CoderDecorator { 
    public GoCoder(Coder coder) {
    super(coder);
    }
    public void codeGo() {
    System.out.println("用Go语言写代码...");
    }
    @Override
    public void code() {
    super.code();
    codeGo();
    }
    }

此时,当我们需要既有Java语言code能力,又有Go语言code能力的程序员时,只要用CoderDecorator类和CoderDecorator类去装饰ConcreteCoder类就行了,而不需要再新增类。

  • 调用类

    public class Client {    public static void main(String[] args) {        Coder coder = new GoCoder(new JavaCoder(new ConcreteCoder()));        coder.code();    }}
  • 输出结果

    会写代码的程序员...用Java语言写代码...用Go语言写代码...

到此,我们就通过装饰器模式实现了功能的动态增加。

装饰器模式总结

  • 优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
  • 缺点:多层装饰比较复杂。