JAVA设计模式:装饰模式
前面我们学习了代理模式:
代理模式主要使用了java的多态,干活的是被代理类,代理类主要是接活,你让我干活,好,我交给幕后的类去干,你满意就成,那怎么知道被代理类能不能干呢?同根就成,大家知根知底,你能做啥,我能做啥都清楚得很,同样一个接口。
本次我们学习下装饰模式:
装饰模式又称为包装模式,装饰模式以对客户端透明的方式扩展对象功能,相对于代理而言,代理是不让客户端知道真实对象的信息,装饰模式是基层关系的一个替代方案。
装饰模式是采用对客户端透明的方式动态的给一个对象添加了更多职责,对于原来被装饰的对象而言在装饰前和后并没有什么不同。装饰模式可以在不使用创造更多子类的情况下扩展对象的功能。
类图如下:

Component:组件对象的接口,规范那些准备添加附加功能类的对象。
ConcreateComponent:具体的组件对象,实现组件对象接口,通常就是被装饰的原始对象,也就是可以给这个对象添加附加的功能。
Decorator:所有装饰器的抽象父类,需要定义一个与组件对象一致的接口,并且持有一个Component对象,其实就是原始对象,被装饰的对象。
ConcreateDecorator:实际的装饰对象,实现具体要像被装饰对象添加的功能。
抽象的接口:
package com.njupt.study.designmodle.decorator;
public interface Component {
public void operation();
}
原始对象,即需要被装饰的对象:
package com.njupt.study.designmodle.decorator;
public class ConcreateComponent implements Component{
public ConcreateComponent(){};
@Override
public void operation()
{
System.out.println("开车");
}
}
所有装饰对象的父类:
package com.njupt.study.designmodle.decorator;
public abstract class Decorator implements Component {
private Component component;
public Decorator(Component component)
{
this.component = component;
}
public void operation()
{
this.component.operation();
}
}
实际装饰对象A:
package com.njupt.study.designmodle.decorator;
public class ConCreateDecoratorA extends Decorator {
public ConCreateDecoratorA(Component component) {
super(component);
}
public void addedOperation()
{
System.out.println("晚上");
}
public void operation()
{
addedOperation();
super.operation();
}
}
实际装饰对象B:
package com.njupt.study.designmodle.decorator;
public class ConCreateDecoratorB extends Decorator {
public ConCreateDecoratorB(Component component) {
super(component);
}
public void addedOperation()
{
System.out.println("兜风");
}
public void operation()
{
super.operation();
addedOperation();
}
}
客户端:
package com.njupt.study.designmodle.decorator; public class Client
{
public static void main(String[] args) {
Component component = new ConcreateComponent(); Decorator decorator = new ConCreateDecoratorB(new ConCreateDecoratorA(component));
decorator.operation();
} }
测试结果:

装饰模式的定义 : 透明的给一个对象添加功能,并能够实现功能的动态组合.
在装饰模式的实现中,为了能够实现和原来使用被装饰对象的代码无缝结合,是通过定义一个抽象类,让这个类实现与被装饰对象相同的接口,然后在具体的实现类中,转调被装饰的对象,在转调的前后添加新的功能,这就实现了给被装饰对象增加功能.
下面举一个实际的例子:
定义一个接口:
package com.njupt.study.designmodle.decorator; /**
* 定义被装饰者 和 装饰者 共同的接口
* @author Pony
*
*/
public interface Human
{
public void wearClothes(); public void walkToWhere();
}
定义原始对象:
package com.njupt.study.designmodle.decorator; /**
* 定义被装饰者,被装饰者初始状态有些自己的装饰
* @author Pony
*
*/
public class Person implements Human { @Override
public void walkToWhere() {
System.out.println("穿什么呢。。"); } @Override
public void wearClothes() {
System.out.println("去哪里呢。。");
} }
定义装饰对象:
package com.njupt.study.designmodle.decorator;
public class DecoratorHuman implements Human {
private Human human;
public DecoratorHuman(Human human) {
this.human = human;
}
public void wearClothes() {
human.wearClothes();
}
public void walkToWhere() {
human.walkToWhere();
}
}
下面定义三种装饰,这是第一个,第二个第三个功能依次细化,即装饰者的功能越来越多
package com.njupt.study.designmodle.decorator;
public class Decorator_zero extends DecoratorHuman {
public Decorator_zero(Human human) {
super(human);
// TODO Auto-generated constructor stub
}
public void goHome() {
System.out.println("进房子。。");
}
public void findMap() {
System.out.println("书房找找Map。。");
}
@Override
public void wearClothes() {
// TODO Auto-generated method stub
super.wearClothes();
goHome();
}
@Override
public void walkToWhere() {
// TODO Auto-generated method stub
super.walkToWhere();
findMap();
}
}
package com.njupt.study.designmodle.decorator;
public class Decorator_first extends DecoratorHuman {
public Decorator_first(Human human) {
super(human);
}
public void goClothespress() {
System.out.println("去衣柜找找看。。");
}
public void findPlaceOnMap() {
System.out.println("在Map上找找。。");
}
@Override
public void wearClothes() {
// TODO Auto-generated method stub
super.wearClothes();
goClothespress();
}
@Override
public void walkToWhere() {
// TODO Auto-generated method stub
super.walkToWhere();
findPlaceOnMap();
}
}
package com.njupt.study.designmodle.decorator;
public class Decorator_two extends DecoratorHuman {
public Decorator_two(Human human) {
super(human);
}
public void findClothes() {
System.out.println("找到一件D&G。。");
}
public void findTheTarget() {
System.out.println("在Map上找到神秘花园和城堡。。");
}
@Override
public void wearClothes() {
// TODO Auto-generated method stub
super.wearClothes();
findClothes();
}
@Override
public void walkToWhere() {
// TODO Auto-generated method stub
super.walkToWhere();
findTheTarget();
}
}
客户端:
package com.njupt.study.designmodle.decorator;
public class Test {
public static void main(String[] args) {
Human person = new Person();
DecoratorHuman decorator = new Decorator_two(new Decorator_first(
new Decorator_zero(person)));
decorator.wearClothes();
decorator.walkToWhere();
}
}
测试结果:

其实就是进房子找衣服,然后找地图这样一个过程,通过装饰者的三层装饰,把细节变得丰富。
关键点:
1、Decorator抽象类中,持有Human接口,方法全部委托给该接口调用,目的是交给该接口的实现类即子类进行调用。
2、Decorator抽象类的子类(具体装饰者),里面都有一个构造方法调用super(human),这一句就体现了抽象类依赖于子类实现即抽象依赖于实现的原则。因为构造里面参数都是Human接口,只要是该Human的实现类都可以传递进去,即表现出Decorator dt = new Decorator_second(new Decorator_first(new Decorator_zero(human)));这种结构的样子。所以当调用dt.wearClothes();dt.walkToWhere()的时候,又因为每个具体装饰者类中,都先调用super.wearClothes和super.walkToWhere()方法,而该super已经由构造传递并指向了具体的某一个装饰者类(这个可以根据需要调换顺序),那么调用的即为装饰类的方法,然后才调用自身的装饰方法,即表现出一种装饰、链式的类似于过滤的行为。
3、具体被装饰者类,可以定义初始的状态或者初始的自己的装饰,后面的装饰行为都在此基础上一步一步进行点缀、装饰。
4、装饰者模式的设计原则为:对扩展开放、对修改关闭,这句话体现在我如果想扩展被装饰者类的行为,无须修改装饰者抽象类,只需继承装饰者抽象类,实现额外的一些装饰或者叫行为即可对被装饰者进行包装。所以:扩展体现在继承、修改体现在子类中,而不是具体的抽象类,这充分体现了依赖倒置原则,这是自己理解的装饰者模式。
JAVA设计模式:装饰模式的更多相关文章
- Java设计模式---装饰模式
装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式的结构 装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任.换言之,客户 ...
- Java设计模式-装饰模式(Decorator)
顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下: Source类是被装饰类,Decorator类是一个 ...
- Java设计模式—装饰模式
装饰模式是一种比较常见的模式. 定义为:动态的给一个对象添加一些额外的职责.就增加功能来说,装饰模式比生成子类更加灵活. 装饰模式的通用类图如下: 装饰模式的构成: 1) 抽象构件(Component ...
- Java设计模式——装饰模式
转载自:http://blog.csdn.net/xu__cg/article/details/53024490 抽象构件 public interface CarInterface { void m ...
- Java设计模式学习记录-装饰模式
前言 装饰模式也是一种结构型模式,主要是目的是相对于类与类之间的继承关系来说,使用装饰模式可以降低耦合度.JDK中有不少地方都使用到了装饰模式,例如Java的各种I/O流,javax.swing包中一 ...
- Java设计模式(7)装饰模式(Decorator模式)
Decorator常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这 ...
- Java设计模式(三) 抽象工厂模式
原创文章,同步发自作者个人博客,转载请注明出处 http://www.jasongj.com/design_pattern/abstract_factory/ 抽象工厂模式解决的问题 上文<工厂 ...
- Java设计模式(十二) 策略模式
原创文章,同步发自作者个人博客,http://www.jasongj.com/design_pattern/strategy/ 策略模式介绍 策略模式定义 策略模式(Strategy Pattern) ...
- Java设计模式(二) 工厂方法模式
本文介绍了工厂方法模式的概念,优缺点,实现方式,UML类图,并介绍了工厂方法(未)遵循的OOP原则 原创文章.同步自作者个人博客 http://www.jasongj.com/design_patte ...
- Java设计模式(一) 简单工厂模式不简单
摘要:本文介绍了简单工厂模式的概念,优缺点,实现方式,以及结合Annotation和反射的改良方案(让简单工厂模式不简单).同时介绍了简单工厂模式(未)遵循的OOP原则.最后给出了简单工厂模式在JDB ...
随机推荐
- 完美分割字符串,实现字符串的splict功能
class Str:Client_C { string val; string[] str = new string[100]; public void StrT1() { //1.正常情况 //2. ...
- cocos2d-x 定时器selector的使用 :schedule的使用
在游戏设计时,我们需要不断的改变屏幕显示来反映游戏操作的效果,最简单的就是提示用户已经进行的游戏时间.为此,我们需要使用cocos2d-x内置的任务调度机制,即CCNode的schedule成员函数. ...
- java中的Set的使用以及各种遍历方法(较为全面)
1. 概述 Java 中的Set和正好和数学上直观的集(set)的概念是相同的.Set最大的特性就是不允许在其中存放的元素是重复的.根据这个特点,我们就可以使用Set 这个接口来实现前面提到的关于商品 ...
- js 回车触发事件
<script type="text/javascript" language=JavaScript > document.onkeydown=function(eve ...
- Round Numbers(poj 3252)
题意:算出区间内二进制中0的个数大于等于1的个数的数字有多少个 /* 本来以为用数位DP搞,但是组合数更简单. 我们设n的二进制长度为len. ①:先考虑长度小于len的数字. 这里以数字22为例,二 ...
- sql相关语言
SQL 掌握一门编程语言: C C++ Java C# ... 数据库 数据结构/算法 链表 队列 栈 数组 面向对象 网络 (界面.业务逻辑) 关系型数据库: 以二维表的形式组织数据 表.索引.视图 ...
- DDD设计一个电商网站
DDD设计一个电商网站(十一)-- 最后的准备 阅读目录 前言 准备 实现 结语 一.前言 最近实在太忙,上周停更了一周.按流程一步一步走到现在,到达了整个下单流程的最后一公里--结算页的处理. ...
- Cassandra 单机入门例子——有索引
入门例子: http://wiki.apache.org/cassandra/GettingStarted 添加环境变量并source生效,使得可以在任意位置执行cassandra/bin安装目录下的 ...
- 5分钟了解MySQL5.7的Online DDL雷区
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://suifu.blog.51cto.com/9167728/1855872 Part ...
- 滚动视图(ScrollView)的功能与用法
滚动视图ScrollView由FrameLayout派生而出,它就是一个用于为普通组件添加滚动条的组件.ScrollView里最多只能包含一个组件,而ScrollVew的作用就是为该组件添加垂直滚动条 ...