Java设计模式07:常用设计模式之装饰器模式(结构型模式)
1. Java之装饰器模式(Decorator Pattern)
(1)概述:
装饰模式在Java种使用也很广泛,比如我们在重新定义按钮、对话框等时候,实际上已经在使用装饰模式了。在不必改变原类文件和使用继承的情况下,装饰模式使用一种对客户端透明的方式来动态地扩展对象的功能,同时它也是继承关系的一种替代方案之一,它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
装饰者模式:动态地给一个对象添加一些额外的职责,就像在墙上刷油漆一样。就增加功能来说,Decorator模式比生成子类更为灵活。
Decorator模式的工作原理是:可以创建始于Decorator对象(负责新的功能的对象)终于原对象的一个对象"链"
图1 装饰者链
装饰模式的特点:
(2)装饰模式的UML类图:
抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,即可以给这些对象动态地添加职责。
具体组件角色(ConcreteComponent) :被装饰者,定义一个将要被装饰增加功能的类。可以给这个类的对象添加一些职责
抽象装饰器(Decorator):维持一个指向构件Component对象的实例,并定义一个与抽象组件角色Component接口一致的接口
具体装饰器角色(ConcreteDecorator):向组件添加职责。
(3)下面是装饰者模式通用模式代码:
/******************抽象组件类**************/
public abstract class Component {
/**
* 抽象的方法,这个随你做
* 同样第你也可以增加更多的抽象方法
*/
public abstract void operate();
} /******************组件具体实现类**************/
public class ConcreteComponent extends Component {
@Override
public void operate() {
//具体逻辑,这个随你做
}
} /******************抽象装饰者**************/
public abstract class Decorator extends Component {
private Component component;//持有一个Component对象的引用
/*
*必要的构造方法 需要一个Component类型的对象
*
* @param component Component对象
*/
public Decorator(Component component) {
this.component = component;
} @Override
public void operate() {
component.operate();
} } /******************装饰者具体实现类A**************/
public class ConcreteDecoratorA extends Decorator {
protected ConcreteDecoratorA(Component component) {
super(component);
} @Override
public void operate() {
//装饰方法A和B既可在父类方法前调用也可在之后调用
operateA(); super.operate(); operateB();
} /**
* 自定义的装饰方法A
*/
public void operateA() {
//装饰方法的逻辑
} /**
* 自定义的装饰方法B
*/
public void operateB() {
//装饰方法的逻辑
}
} /******************装饰者具体实现类B**************/
public class ConcreteDecoratorB extends Decorator { protected ConcreteDecoratorB(Component component) {
super(component);
} @Override
public void operate() {
//装饰方法A和B既可在父类方法前调用也可在之后调用
operateA(); super.operate(); operateB();
} /**
* 自定义的装饰方法A
*/
public void operateA() {
//装饰方法的逻辑
} /**
* 自定义的装饰方法B
*/
public void operateB() {
//装饰方法的逻辑
}
} /******************客户调用类**************/
public class Client {
public static void main(String[] args) {
//构建被装饰的组件对象
Component component = new Component(); //根据组件对象构建装饰者对象A并调用,此时相当于给组件对象增加装饰者A的功能方法
Decorator decorator = new ConcreteDecoratorA(component);
decorator.operate(); //根据组件对象构建装饰者对象B并调用,此时相当于给组件对象增加装饰者B的功能方法
Decorator decoratorB = new ConcreteDecoratorB(component);
decoratorB.operate();
}
}
2. 装饰器模式简单实现:
人需要各式各样的衣着,不管你穿着怎么样,但是,对于个人的本质来说是不可变的,充其量只是在外面披上一层遮羞物。
(1)人总是需要穿衣服的,我们这里将人定义一个抽象类,将穿衣的行为定义一个抽象方法:
抽象组件类:
public abstract class Person {
/**
* Person 下有一个穿着的抽象方法
*/ public abstract void dressed();
}
(2)接下来我们需要具体装饰谁呢? 也就是说我们需要创建一个具体组件类,如下:
具体组件类:
public class Boy extends Person { @Override
public void dressed() {
//Boy 类下dressed方法的基本逻辑
System.out.println("穿了内衣内裤");
}
}
(3)上面的Boy类就是我们所要装饰的具体对象,现在需要一个装饰者来装饰我们的这个Boy对象,这里定义一个PersonCloth类来表示人所穿着的衣服
抽象装饰者类:
public abstract class PersonCloth extends Person {
protected Person mPerson;//保持一个Person类的引用 public PersonCloth(Person mPerson) {
this.mPerson = mPerson;
} @Override
public void dressed() {
//调用Person类中的dressed方法 mPerson.dressed();
}
}
在PersonCloth类中我们保持一个对Person的引用,这样就可以方便地调用具体被装饰对象中的方法,这也是为什么我们可以在不破坏原类层次结构的情况下为类增加一些功能,我们只需要在被装饰对象的相应方法前 或者 后 增加相应的功能逻辑即可。
(4)定义两种装饰具体实现类,如下:
装饰具体实现类之 高档衣服:
public class ExpensiveCloth extends PersonCloth {
public ExpensiveCloth(Person person) {
super(person);
} //穿短袖
private void dressShirt() {
System.out.println("穿件短袖");
} //穿皮衣
private void dressLeather(){
System.out.println("穿件皮衣");
} //穿牛仔裤
private void dressJean(){
System.out.println("穿牛仔裤");
} @Override
public void dressed() {
super.dressed(); dressShirt();
dressLeather();
dressJean();
} }
装饰具体实现类之 便宜的衣服:
public class CheapCloth extends PersonCloth { public CheapCloth(Person mPerson) {
super(mPerson);
} //穿短袖
private void dressShorts() {
System.out.println("穿件短袖");
} @Override
public void dressed() {
super.dressed(); dressShorts();
}
}
(5)客户端类:
public class Main { public static void main(String[] args) {
//首先我们要有一个Person男孩
Person person = new Boy(); //然后为他穿上便宜的衣服,比如爱哥这样的Boy
PersonCloth clothCheap = new CheapCloth(person);
clothCheap.dressed(); //或者给他穿上比较上档次的衣服,如SM
PersonCloth clothExpensive = new ExpensiveCloth(person);
clothExpensive.dressed();
} }
Java设计模式07:常用设计模式之装饰器模式(结构型模式)的更多相关文章
- Java 23种设计模式详尽分析与实例解析之二--结构型模式
Java设计模式 结构型模式 适配器模式 模式动机:在软件开发中采用类似于电源适配器的设计和编码技巧被称为适配器模式.通常情况下,客户端可以通过目标类的接口访问它所提供的服务.又是,现有的类可以满足客 ...
- 设计模式(十二): Flyweight享元模式 -- 结构型模式
说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面 ...
- 设计模式(十):Decorator装饰者模式 -- 结构型模式
1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继 ...
- 设计模式(十三): Proxy代理模式 -- 结构型模式
设计模式(十一)代理模式Proxy(结构型) 1.概述 因为某个对象消耗太多资源,而且你的代码并不是每个逻辑路径都需要此对象, 你曾有过延迟创建对象的想法吗 ( if和else就是不同的两条逻辑路 ...
- 设计模式学习之路——Facade 外观模式(结构型模式)
动机: 组件的客户和组件中各种复杂的子系统有了过多的耦合,随着外部客户程序和各子系统的演化,这种过多的耦合面临很多变化的挑战.如何简化外部客户程序和系统间的交互接口?如何将外部客户程序的演化和内部子系 ...
- 设计模式(八):Bridge桥接模式 -- 结构型模式
1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度 ...
- Decorator装饰者模式(结构型模式)
1.需求 假设让我们去设计FCL中的Stream类,该类具有流类的基本功能,除了有各种不同类型的流外(如内存流.文件流.网络流等等),但是在不同的业务场景下,如处理银行业务,需要给相关的内存流进行加密 ...
- 设计模式(九):Composite组合模式 -- 结构型模式
1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件和文件夹目录 2.问题 我们可以使用简单的对象组合成复杂的对象,而这个复杂对 ...
- 设计模式(十一):FACADE外观模式 -- 结构型模式
1. 概述 外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性.例子1:一个电源总开关可以控制四盏灯.一个风扇 ...
- Decorator(装饰)-对象结构型模式
1.意图 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活. 2.别名 包装器 Wrapper. 3.动机 给某个对象而不是整个类添加一些功能.一个较为灵 ...
随机推荐
- 【Jenkins】linux下Jenkins集成ant进行编译并发送结果
三个文章吧: 1 如何使用ant编译执行jmeter测试用例,并生成html报告 2 如何在Linux下搭建jenkins环境. 3 如何在Linux下搭建的jenkins中执行ant构建运行,并发送 ...
- Travel(HDU 4284状压dp)
题意:给n个城市m条路的网图,pp在城市1有一定的钱,想游览这n个城市(包括1),到达一个城市要一定的花费,可以在城市工作赚钱,但前提有工作证(得到有一定的花费),没工作证不能在该城市工作,但可以走, ...
- 单元测试工具之Xunit
在.NET开发中的单元测试工具之——xUnit.Net 原始出处 http://zhoufoxcn.blog.51cto.com/792419/1172320 在上一篇<在.NET开发中的单元 ...
- [tensorflow in a nutshell] tensorflow简明教程 (第一部分)
原文链接: https://medium.com/@camrongodbout/tensorflow-in-a-nutshell-part-one-basics-3f4403709c9d#.31jv5 ...
- POJ 3254 poj3254 Corn Fields
题意:给出一个n行m列的草地,1表示肥沃,0表示贫瘠,现在要把一些牛放在肥沃的草地上,但是要求所有牛不能相邻,问你有多少种放法. 思路: DP[i][j]=sum(dp[i-1][k]); i表示当前 ...
- MyEclipse 10优化技巧
MyEclipse 10优化速度方案仍然主要有这么几个方面:去除无需加载的模块.取消冗余的配置.去除不必要的检查.关闭更新. 第一步: 去除不需要加载的模块 一个系统20%的功能往往能够满足80%的需 ...
- leetcode—word ladder II
1.题目描述 Given two words (start and end), and a dictionary, find all shortest transformation sequence( ...
- 【AC自动机】专题总结
刷了一星期+的ac自动机的题目 做一个总结~ 我的ac自动机是之前省选的时候看老师给的一个网页上学的 由于找不到原文 就贴个转载的地址吧 - - http://hi.baidu.com/winterl ...
- BNUOJ-29358 Come to a spring outing 搜索,DP
题目链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=29358 状态虽然很多,但是非常稀疏,dfs搜索然后剪下枝.. 或者DP,f[i][j][k ...
- HDU 3488--Tour(KM or 费用流)
因为每个点只能经过一次 所以考虑拆点 这题有坑,有重边.. KM算法 把一个点拆成入点和出点 入点在X部,出点在Y步. 如果u,v之间有路径,就在X部的u点连接Y部的v点 求完美匹配. 当完美匹配的时 ...