GOF的设计模式,讲的很细,我这里都很粗略。什么意图,别名,参与者,结构,协作,效果等等。。。
我这等小民,也没有那么高深的理论,拾人牙慧就满足了。
模式是死的,运用是活的。
今天讲讲装饰器模式。其实 每个模式的名字都很重要,因为这个名字基本就说明了这个模式用来干什么。当然,装饰器,不是用来装饰的,但是和装饰相关。
比如,我们设计一个窗子,完了,觉得太单调,于是重新加上边框,还觉得单调,那就贴点窗纸吧,如果还是不满意,那么可以糊个纱窗……
如果用程序来实现,我们可能想到这些对象,窗子,加边框的窗子,贴窗纸的窗子(好拗口),加边框贴窗纸的窗子…… 其实这种错误只会在初学者身上犯。
首先,我们的对象的粒度,应该合适,这样通过面向对象的重复利用,组合,就可以实现很多奇怪的东西。这里,我们有必要把窗,窗纸,边框,窗纱等看单独的对象,再细分,发现,其他都是作为装饰品,为窗服务的。于是,一个大概的参与者思路就清晰了。
然后,如何组织这些类呢?由于他们都与窗有关,那么,肯定又一个共同点,我们可以抽象成一个接口。然后,窗,与其他的东西又不一样,那么又可以分别对待。
最后,我们大概可以得出一个结构图了。这里使用标准的装饰器模式的UML:
图中的Component,应该就是要装饰的对象的抽象,注意,饰品也是可以被装饰的,但是必须有一实际的被装饰对象(下面会说明为什么)。
Decorator接口把装饰器隔离出来,表明这些是装饰器。
每个装饰器需要一个可装饰的 被装饰对象,这就是ConcreteComponent了。为了强制要求装饰器必须装饰一个可装饰对象,我们在构造函数里做了要求。
下面就来看一个小例子。本例子完全只是为了说明模式的结构运用,实际的情况只能如有雷同,实属巧合。
一个接口,这是可被装饰对象的统一接口,表明他们能做什么。
public interface VisualComponent {
public void draw();
}
这是一个可视组件。他的方法就是画出自己。也可以使用抽象类。
某些组件可能有共同的方法。这里为了简化,直接说关键。
public class Pane implements VisualComponent{
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println("drawing pane...");
}
}
这是一块面板,我们省略了绘制过程,并打印出一串字符,表示正在绘制此组件。
接下来,我们就要给这个可视化组件做装饰了。当然,不仅仅是Pane可以被装饰,只要是实现了VisualComponent接口的类都可以被装饰。
首先要有一个装饰器的接口。
public abstract class ComponentDecorator implements VisualComponent{
protected VisualComponent visualComponent ;
public ComponentDecorator(VisualComponent vc){
this.visualComponent = vc;
}
}
这里使用了抽象类,如果使用接口也可以,直接继承 VisualComponent就行。
之所以使用抽象类,是为了确保子类使用父类的构造函数来完成装饰器应有的职责,那就是我们只是装饰者,应该提供一个被装饰者给我。
接下来,是具体的装饰器了,我们定义两个,这样可以看到使用情况。
首先是一个边框装饰器。
public class BorderDecorator extends ComponentDecorator{
public BorderDecorator(VisualComponent vc){
super(vc);
}
@Override
public void draw() {
// TODO Auto-generated method stub
visualComponent.draw();
System.out.println("draw bording...");
}
}
可以看到,他所装饰的类,是通过继承父类构造函数来实现的。
在绘制时,我们先绘制父类,然后绘制自己(代码中省略)。
然后再来一个头装饰器,也就是绘制一个顶栏的装饰器。
public class HeaderDecorator extends ComponentDecorator{
public HeaderDecorator(VisualComponent vc){
super(vc);
}
@Override
public void draw() {
// TODO Auto-generated method stub
visualComponent.draw();
System.out.println("drawing header...");
}
}
好了,我们的装饰器好了,现在来看看如何使用。
装饰器模式,通过不同的修饰顺序,我们可以得到不同的结果。这里如何组装,
是使用者决定的。
public class TestMain {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
VisualComponent vc = new Pane();
VisualComponent newVC = new HeaderDecorator(new BorderDecorator(vc));
newVC.draw();
}
}
看着是不是眼熟,这个其实和java中的I/O很眼熟;
InputStream ins = new BufferedInputStream(new FileInputStream("xx.txt"));
没错,java.io 下的类就是使用了装饰器模式(当然还有其他的比如Adapter)
从网上找到一张图,很能说明问题,相信大家看完以后,对 java.io里的那么多类,会有一个新的认识。
这个图好像是《Head First 设计模式》的吧。。。嘿嘿,我也没看这本书,但是风格很像。
到这里,我们对装饰器模式应该有个大概的认识了。这里,也可以看到,装饰器模式,其实很适合用于链式过滤,每一层都灵活控制。
这点很像OSI的七层协议,每一层,都添加一个头(做个装饰)。
我们也看看自己有什么设计上需要用到装饰器模式的吧,赶快动手试试效果。

- 大小: 8.6 KB

- 大小: 47.8 KB
分享到:
相关推荐
解释器模式将描述怎样 在 有了一个简单的文法后, 使用模式设计解释这些语句。 在解释器模式里面提到的语言是指任 何解释器对象能够解释的任何组合。在解释器模式中需要定义一个代表 文法的命令类的等 级结构,也...
收据装饰器由 Patrick Hickey 在 2014 年为 Towson U 的 OOD 课程创建的装饰器设计模式示例Headers、Coupons 和 Rebates 套餐是独立的,因为我们假设它们每天都从 bestbuy 网站上提取。 我们假设主要知道如何使用...
人脸识别项目实战
内容概要:本文详细描述了一个完整的Web应用程序的开发过程。该项目主要采用了Hono作为服务器框架,Prisma作为ORM工具,JWT用于认证鉴权,以及一系列现代化的最佳实践确保系统的健壮性和安全性。项目初期构建了基础架构,并设置了必要的依赖和工具。在后端方面涵盖了公共API接口的设计、CRUD增删改查逻辑、用户认证和授权等功能。此外还特别关注到了API的安全保护,如输入输出的校验,跨站请求伪造CSRF的防范,XSS防御等措施;为确保代码的质量引入了代码检测(比如ESLint搭配Prettier),并建立了完善的测试框架以保障后续开发阶段的功能正确。对于可能出现的问题预先定义了一组规范化的异常响应,并提供OpenAPI文档以方便开发者理解和调用。数据存储层面上利用了关系型与非关系型数据库各自的特性,实现了数据的有效组织,最后提供了实用的脚本,可用于种子数据插入以及执行必要的初始化工作。 适合人群:面向具有一定JavaScript/TypeScript开发经验,尤其是Node.js后台服务搭建经验的中级程序员和技术团队。 使用场景及目标:这份材料非常适合那些需要快速建立安全高效的RES
【资源介绍】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,也可以作为小白实战演练和初期项目立项演示的重要参考借鉴资料。 3、本资源作为“学习资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研和多多调试实践。 掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip掌静脉识别算法源码(门禁).zip
手势识别项目实战
(参考GUI)MATLAB BP的交通标志系统.zip
人脸识别项目实战
内容概要:本文详细介绍了 C++ 函数的基础概念及其实战技巧。内容涵盖了函数的基本结构(定义、声明、调用)、多种参数传递方式(值传递、引用传递、指针传递),各类函数类型(无参无返、有参无返、无参有返、有参有返),以及高级特性(函数重载、函数模板、递归函数)。此外,通过实际案例展示了函数的应用,如统计数组元素频次和实现冒泡排序算法。最后,总结了C++函数的重要性及未来的拓展方向。 适合人群:有一定编程基础的程序员,特别是想要深入了解C++编程特性的开发人员。 使用场景及目标:① 学习C++中函数的定义与调用,掌握参数传递方式;② 掌握不同类型的C++函数及其应用场景;③ 深入理解函数重载、函数模板和递归函数的高级特性;④ 提升实际编程能力,通过实例强化所学知识。 其他说明:文章以循序渐进的方式讲解C++函数的相关知识点,并提供了实际编码练习帮助理解。阅读过程中应当边思考边实践,动手实验有助于更好地吸收知识点。
Comsol光学仿真模型:包括纳米球 柱 Mie散射多级分解 ,Comsol光学仿真模型; 纳米球; 柱; Mie散射; 多级分解,Comsol光学仿真模型:纳米结构Mie散射多级分解
永磁同步电机全速域控制高频方波注入法、滑模观测器法SMO、加权切矢量控制Simulink仿真模型 低速域采用高频方波注入法HF,高速域采用滑膜观测器法SMO,期间采用加权形式切 送前方法 1、零低速域,来用无数字滤波器高频方波注入法, 2.中高速域采用改进的SMO滑模观测器,来用的是sigmoid函数,PLL锁相环 3、转速过渡区域采用加权切法 该仿真各个部分清晰分明,仿真波形效果良好内附详细控制方法资料lunwen 带有参考文献和说明文档,仿真模型 ,核心关键词: 1. 永磁同步电机; 2. 全速域控制; 3. 高频方波注入法; 4. 滑模观测器法SMO; 5. 加权切换矢量控制; 6. Simulink仿真模型; 7. 零低速域控制; 8. 中高速域控制; 9. 转速过渡区域控制; 10. 仿真波形效果; 11. 详细控制方法资料; 12. 参考文献和说明文档。,永磁同步电机多域控制策略的仿真研究
基于蜣螂优化算法的无人机三维路径规划【23年新算法应用】可直接运行 Matlab语言 主要内容:读取地形数据,利用蜣螂算法DBO优化三维路径,目标函数为总路径最短,同时不能撞到障碍物,效果如图所示,包括迭代曲线图、三维路径图、二维平面图等等 ,基于蜣螂优化算法;无人机;三维路径规划;总路径最短;障碍物避免;Matlab语言;迭代曲线图;三维路径图;二维平面图,蜣螂算法优化无人机三维路径规划:实时避障、路径最短新应用
清华大学2024年研究生复试上机考试题.zip
南京理工大学研究生入学考试2011年复试上机试题
手势识别项目实战
这里是3501的内容,用于复习资料
异步电动机变压变频调速系统,包含六千多字的文档、框架图、Simulink仿真模型,电力拖动、电机控制仿真设计 仿真模型+报告 开关闭环对比仿真都有,资料如图所见如所得 ,异步电动机;变压变频调速系统;六千字文档;框架图;Simulink仿真模型;电力拖动;电机控制仿真设计;开闭环对比仿真;资料如图。,异步电机控制仿真系统:六千字详解与图解
人脸识别项目实战