热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入理解Java设计模式:装饰者模式

本文详细介绍了装饰者(Decorator)模式,这是一种动态地为对象添加职责的方法。与传统的继承方式不同,装饰者模式通过组合而非继承来实现功能扩展,从而提供更大的灵活性和可维护性。

一、基本概念

1. 定义

装饰者模式,也称为包装模式,允许在不改变原有类结构的前提下,动态地给对象增加新的行为或属性。它通过将对象封装在另一个对象中,使得新对象可以在调用原对象的基础上进行增强。相比子类化,装饰者模式提供了更灵活的解决方案。

该模式的关键在于,它可以在不影响其他对象的情况下,透明地扩展对象的功能。这种特性使得装饰者模式在需要动态调整功能的应用场景中非常有用,如Java I/O流处理。

2. 适用环境

装饰者模式适用于以下情况:

  • 需要在不影响其他对象的情况下,动态地为单个对象添加职责。
  • 需要支持可以撤销的职责。
  • 当不能使用子类化方法进行扩展时,例如有大量独立的扩展需求,或者类定义被隐藏无法生成子类。

3. 角色

  • 抽象构件(Component):通常是一个接口或抽象类,定义了组件的基本操作。具体实现由其子类完成。
  • 具体构件(Concrete Component):实现了抽象构件定义的操作,是被装饰的对象。
  • 装饰角色(Decorator):持有一个抽象构件的引用,负责将客户端请求转发给被装饰对象,并在其基础上进行增强。
  • 具体装饰角色(Concrete Decorator):具体的装饰类,继承自装饰角色,实现特定的增强功能。

4. UML图解

UML图解


二、代码实现

为了更好地理解装饰者模式的工作原理,我们可以通过一个简单的示例来展示其实现过程。

1. 抽象构件——IComponentOutput接口

public interface IComponentOutput { void operator(); }

2. 具体构件——Output类

public class Output implements IComponentOutput { @Override public void operator() { System.out.println("输出字节流"); } }

3. 装饰角色——AbstractBuffer抽象类

public abstract class AbstractBuffer implements IComponentOutput { private IComponentOutput output; public AbstractBuffer(IComponentOutput output) { this.output = output; } @Override public void operator() { output.operator(); } }

4. 具体装饰角色——Buffer1类

public class Buffer1 extends AbstractBuffer { public Buffer1(IComponentOutput output) { super(output); } @Override public void operator() { super.operator(); this.b1(); } void b1() { System.out.println("附加1"); } }

5. 具体装饰角色——Buffer2类

public class Buffer2 extends AbstractBuffer { public Buffer2(IComponentOutput output) { super(output); } @Override public void operator() { super.operator(); this.b2(); } void b2() { System.out.println("附加2"); } }

6. 具体装饰角色——Buffer3类

public class Buffer3 extends AbstractBuffer { public Buffer3(IComponentOutput output) { super(output); } @Override public void operator() { super.operator(); this.b3(); } void b3() { System.out.println("附加3"); } }

以上三个具体装饰类分别实现了不同的附加功能。

7. 测试类——Client类

public class Client { public static void main(String[] args) { IComponentOutput output = new Output(); output.operator(); System.out.println("===定制1==="); AbstractBuffer b1 = new Buffer1(output); AbstractBuffer b2 = new Buffer2(b1); b2.operator(); System.out.println("===定制2==="); AbstractBuffer b3 = new Buffer3(output); b3.operator(); } }

执行结果如下:
输出字节流
===定制1===
输出字节流
附加1
附加2
===定制2===
输出字节流
附加3

补充说明

注意,在定制1的方式中:

AbstractBuffer b1 = new Buffer1(output); AbstractBuffer b2 = new Buffer2(b1);

第二次创建的具体装饰类接收的是已经经过装饰的对象。这使得每次调用都会依次触发所有装饰层的操作,确保每个附加功能都能按顺序执行。


推荐阅读
  • 本文详细探讨了UML用例图中的两种重要关系——包含关系和扩展关系,通过具体示例解析这两种关系的应用场景及其实现方式。 ... [详细]
  • java文本编辑器,java文本编辑器设计思路
    java文本编辑器,java文本编辑器设计思路 ... [详细]
  • 本文详细探讨了Java中的ClassLoader类加载器的工作原理,包括其如何将class文件加载至JVM中,以及JVM启动时的动态加载策略。文章还介绍了JVM内置的三种类加载器及其工作方式,并解释了类加载器的继承关系和双亲委托机制。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • NIO 通道接口详解
    本文介绍了NIO(New Input/Output)中的通道接口及其相关概念,包括通道的基本功能、接口设计以及各类通道接口的具体用途。通过本文,读者可以深入了解NIO通道的设计原理及其在实际项目中的应用。 ... [详细]
  • 本文介绍了如何利用Apache Digester库解决硬编码问题,通过创建自定义配置文件(如Struts配置文件)来动态调整应用程序的行为。文章详细描述了使用Apache Digester将XML文档转换为Java Bean对象的过程,并提供了具体的实现步骤。 ... [详细]
  • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
    Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
  • 深入解析Java多线程与并发库的应用:空中网实习生面试题详解
    本文详细探讨了Java多线程与并发库的高级应用,结合空中网在挑选实习生时的面试题目,深入分析了相关技术要点和实现细节。文章通过具体的代码示例展示了如何使用Semaphore和SynchronousQueue来管理线程同步和任务调度。 ... [详细]
  • 主调|大侠_重温C++ ... [详细]
  • 深入理解Java多线程并发处理:基础与实践
    本文探讨了Java中的多线程并发处理机制,从基本概念到实际应用,帮助读者全面理解并掌握多线程编程技巧。通过实例解析和理论阐述,确保初学者也能轻松入门。 ... [详细]
  • ListView简单使用
    先上效果:主要实现了Listview的绑定和点击事件。项目资源结构如下:先创建一个动物类,用来装载数据:Animal类如下:packagecom.example.simplelis ... [详细]
  • 本文将详细探讨 Java 中提供的不可变集合(如 `Collections.unmodifiableXXX`)和同步集合(如 `Collections.synchronizedXXX`)的实现原理及使用方法,帮助开发者更好地理解和应用这些工具。 ... [详细]
  • 为了解决不同服务器间共享图片的需求,我们最初考虑建立一个FTP图片服务器。然而,考虑到项目是一个简单的CMS系统,为了简化流程,团队决定探索七牛云存储的解决方案。本文将详细介绍使用七牛云存储的过程和心得。 ... [详细]
  • 本文详细介绍了虚拟专用网(Virtual Private Network, VPN)的概念及其通过公共网络(如互联网)构建临时且安全连接的技术特点。文章探讨了不同类型的隧道协议,包括第二层和第三层隧道协议,并提供了针对IPSec、GRE以及MPLS VPN的具体配置指导。 ... [详细]
  • 在寻找轻量级Ruby Web框架的过程中,您可能会遇到Sinatra和Ramaze。两者都以简洁、轻便著称,但它们之间存在一些关键区别。本文将探讨这些差异,并提供详细的分析,帮助您做出最佳选择。 ... [详细]
author-avatar
卖火柴的冰枫_939
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有