前面我们学习了代理模式:

代理模式主要使用了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设计模式:装饰模式的更多相关文章

  1. Java设计模式---装饰模式

    装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式的结构 装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任.换言之,客户 ...

  2. Java设计模式-装饰模式(Decorator)

    顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下: Source类是被装饰类,Decorator类是一个 ...

  3. Java设计模式—装饰模式

    装饰模式是一种比较常见的模式. 定义为:动态的给一个对象添加一些额外的职责.就增加功能来说,装饰模式比生成子类更加灵活. 装饰模式的通用类图如下: 装饰模式的构成: 1) 抽象构件(Component ...

  4. Java设计模式——装饰模式

    转载自:http://blog.csdn.net/xu__cg/article/details/53024490 抽象构件 public interface CarInterface { void m ...

  5. Java设计模式学习记录-装饰模式

    前言 装饰模式也是一种结构型模式,主要是目的是相对于类与类之间的继承关系来说,使用装饰模式可以降低耦合度.JDK中有不少地方都使用到了装饰模式,例如Java的各种I/O流,javax.swing包中一 ...

  6. Java设计模式(7)装饰模式(Decorator模式)

    Decorator常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这 ...

  7. Java设计模式(三) 抽象工厂模式

    原创文章,同步发自作者个人博客,转载请注明出处 http://www.jasongj.com/design_pattern/abstract_factory/ 抽象工厂模式解决的问题 上文<工厂 ...

  8. Java设计模式(十二) 策略模式

    原创文章,同步发自作者个人博客,http://www.jasongj.com/design_pattern/strategy/ 策略模式介绍 策略模式定义 策略模式(Strategy Pattern) ...

  9. Java设计模式(二) 工厂方法模式

    本文介绍了工厂方法模式的概念,优缺点,实现方式,UML类图,并介绍了工厂方法(未)遵循的OOP原则 原创文章.同步自作者个人博客 http://www.jasongj.com/design_patte ...

  10. Java设计模式(一) 简单工厂模式不简单

    摘要:本文介绍了简单工厂模式的概念,优缺点,实现方式,以及结合Annotation和反射的改良方案(让简单工厂模式不简单).同时介绍了简单工厂模式(未)遵循的OOP原则.最后给出了简单工厂模式在JDB ...

随机推荐

  1. [转]六款常用的linux C/C++ IDE

    之前在windows下开发习惯啦,linux改用vim开发代码,但是前期还是不熟悉看代码效率感觉有点低.由于看代码需要各种跳转查找我个人觉得还是IDE方便些,以前在windows下就挺喜欢使用code ...

  2. 让DIV的滚动条自动滚动到最底部 - 4种方法

    方法一:使用锚标记要滚动到的位置,然后通过click方法模拟点击滚动到锚所在位置 <script language="javascript1.2" type="te ...

  3. js获取前之前或之后的日期

    function fun_date(aa){ var date1 = new Date(), time1=date1.getFullYear()+"-"+(date1.getMon ...

  4. 3)Java学习笔记:内部类

    什么是内部类 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public和 ...

  5. UVa 412 - Pi

    题目大意:给定一种估算Pi的方法:给出一系列随机数,从中任选两个数,这两个数的最大公约数不大于1(互质)的概率为6/(Pi*Pi),然后给出一系列数,据此估算Pi的值.直接模拟就好了. #includ ...

  6. 【Xilinx-Petalinux学习】-08-OpenAMP系统实现

    openAMP系统实现. 一个核跑Linux,一个核裸跑.     ----->  已经实现. 一个核跑Linux,一个核跑UCOS   ----->  还未实现. Micrium的uco ...

  7. xamarin mac 之 资料

    中文社区 xamarin.form 30天学习计划

  8. ubuntu下常用的apt-get 命令参数

    apt-cache search package 搜索包 apt-cache show package 获取包的相关信息,如说明.大小.版本等 sudo apt-get install package ...

  9. iOS 之 OC开发实战

    iOS 开发之登陆 iOS 程序初始一个带导航栏的视图 iOS 添加导航栏两侧按钮 iOS UITabBar

  10. 用ant打包可运行的jar文件 (将第三方jar包放进你自己的jar包)

    http://blog.csdn.net/caiqcong/article/details/7618582 <span style="font-family:SimSun;font-s ...