Decorator(装饰)

1)意图

动态地给一个对象添加一些额外的职责。就增加功能而言,Decorator 模式比生成子类更加灵活。

2)结构

装饰模式的结构如图 7-34 所示。
在这里插入图片描述
其中:

  • Component 定义一个对象接口,可以给这些对象动态地添加职责。

  • ConcreteComponent 定义一个对象,可以给这个对象添加一些职责。Decorator 维持一个指向 Component 对象的指针,并定义一个与 Component 接口一致的接口。

  • ConcreteDecorator 向组件添加职责。

3)适用性

Decorator 模式适用于:

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

  • 处理那些可以撤销的职责。

  • 当不能采用生成子类的方式进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是,由于类定义被隐藏,或类定义不能用于生成子类。

4 应用举例

示例:HTTP响应装饰者

假设我们正在构建一个Web应用程序,希望对某些HTTP响应进行特殊处理,比如添加安全相关的HTTP头,或者对响应内容进行GZIP压缩以提高传输效率。我们可以使用装饰者模式来实现这些功能。

  1. 定义Component接口

首先,我们需要定义一个接口来表示HTTP响应。

public interface HttpResponse {
    void sendResponse(String content);
}
  1. 创建ConcreteComponent类

然后,我们创建一个实现了HttpResponse接口的具体类,用于发送未经过任何装饰的原始HTTP响应。

public class SimpleHttpResponse implements HttpResponse {
    @Override
    public void sendResponse(String content) {
        System.out.println("发送响应: " + content);
    }
}
  1. 创建Decorator抽象类

接下来,我们创建一个装饰者类,该类持有一个HttpResponse类型的引用,这样我们就可以在实际的响应发送之前或之后添加额外的行为。

public abstract class HttpResponseDecorator implements HttpResponse {
    protected HttpResponse wrapped;

    public HttpResponseDecorator(HttpResponse wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public void sendResponse(String content) {
        wrapped.sendResponse(content);
    }
}
  1. 创建ConcreteDecorator类

现在,我们可以创建具体的装饰者类,用来添加特定的功能,如添加安全头或压缩响应。

  • 添加安全头
public class SecurityHeaderDecorator extends HttpResponseDecorator {
    public SecurityHeaderDecorator(HttpResponse wrapped) {
        super(wrapped);
    }

    @Override
    public void sendResponse(String content) {
        System.out.println("添加安全头: X-Content-Type-Options=nosniff");
        super.sendResponse(content);
    }
}
  • 压缩响应
public class GzipResponseDecorator extends HttpResponseDecorator {
    public GzipResponseDecorator(HttpResponse wrapped) {
        super(wrapped);
    }

    @Override
    public void sendResponse(String content) {
        String compressedContent = compress(content); // 假设这里有一个压缩方法
        System.out.println("压缩响应内容");
        super.sendResponse(compressedContent);
    }

    private String compress(String content) {
        // 这里只是一个示例,实际应用中需要实现真正的压缩逻辑
        return "GZIPPED_" + content;
    }
}
  1. 使用装饰者

最后,我们可以通过组合多个装饰者来构建一个复杂的响应处理流程。

public class WebApp {
    public static void main(String[] args) {
        HttpResponse response = new SimpleHttpResponse();
        response = new SecurityHeaderDecorator(response);
        response = new GzipResponseDecorator(response);

        response.sendResponse("Hello, World!");
        // 输出:
        // 添加安全头: X-Content-Type-Options=nosniff
        // 压缩响应内容
        // 发送响应: GZIPPED_Hello, World!
    }
}

在这个例子中,SecurityHeaderDecoratorGzipResponseDecorator 都是装饰者,它们可以单独或组合使用来增强SimpleHttpResponse的功能。这种设计不仅保持了代码的清晰度和可维护性,还提供了极大的灵活性,使得我们可以根据需要轻松地添加或移除功能。

示例:不同的格式化功能

假设我们要为文本消息添加不同的格式化功能,比如加粗和斜体。我们可以使用装饰者模式来实现这一需求。

  1. 定义Component接口
public interface TextComponent {
    String getText();
}
  1. 创建ConcreteComponent类
public class SimpleText implements TextComponent {
    private String text;

    public SimpleText(String text) {
        this.text = text;
    }

    @Override
    public String getText() {
        return text;
    }
}
  1. 创建Decorator抽象类
public abstract class TextDecorator implements TextComponent {
    protected TextComponent wrapped;

    public TextDecorator(TextComponent wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public String getText() {
        return wrapped.getText();
    }
}
  1. 创建ConcreteDecorator类
public class BoldDecorator extends TextDecorator {
    public BoldDecorator(TextComponent wrapped) {
        super(wrapped);
    }

    @Override
    public String getText() {
        return "<b>" + super.getText() + "</b>";
    }
}

public class ItalicDecorator extends TextDecorator {
    public ItalicDecorator(TextComponent wrapped) {
        super(wrapped);
    }

    @Override
    public String getText() {
        return "<i>" + super.getText() + "</i>";
    }
}
  1. 使用装饰者
public class Main {
    public static void main(String[] args) {
        TextComponent simpleText = new SimpleText("Hello, World!");
        TextComponent boldText = new BoldDecorator(simpleText);
        TextComponent italicBoldText = new ItalicDecorator(boldText);

        System.out.println(italicBoldText.getText()); // 输出: <i><b>Hello, World!</b></i>
    }
}

在这个例子中,SimpleText 是基本的组件,而 BoldDecoratorItalicDecorator 是装饰者,它们可以动态地为文本添加加粗和斜体的格式。通过这种方式,我们可以在不修改原始文本对象的情况下,为其增加新的功能。

装饰者模式的一个主要优点是它提供了比静态继承更大的灵活性。然而,过度使用装饰者可能会导致系统中存在大量小对象,这可能使得代码难以理解和维护。因此,在选择是否使用装饰者模式时,需要权衡其带来的灵活性和可能引入的复杂性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老攀呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值