Java 装饰器模式详解

转载请注明出处:http://blog.csdn.net/zhaoyanjun6/article/details/56488020

前言

在上面的几篇文章中,着重介绍了java 中常见的 IO 相关知识,在学习的过程中,发现 IO 包中是用了大量的装饰器模式,为了彻底的学习 IO,今天就来揭开装饰器模式的面纱。

为了弄明白装饰器模式的本质,我查看了很多资料,发现有很多文章要么说的很苦涩,要么举的例子不恰当。

其实我们可以这样理解装饰器模式, 就拿自己举例子,你把自己裸体的样子,想象成被装饰的对象。你的鞋子,你的寸衣,你的外套,你的手表,你的帽子 等等,都是你的装饰物,你和这些装饰物,是装饰和被装饰的关系。

实例展示

好了,现在我们用代码的方法去理解这样概念。

首先,我们发现,不管是裸体的人,还是你的鞋子、帽子,都有展示的功能,我们称之为show 方法。

我们定义一个接口,它具有展示的功能,也就是show() , 

package com.user;

/**
 * 定义接口
 * @author T
 *
 */
public interface AbstractPerson {

	//具有展示的功能
	void show() ;
}

现在应该定义一个裸体的自己了,Me 类

package com.user;

/**
 * 定义一个具体的人,就是被装饰者
 * @author T
 *
 */
public class Me implements AbstractPerson {

	@Override
	public void show() {
		System.out.println( "什么都没穿,我展示的是裸体");
	}

}

下面该定义,鞋子,帽子,手表等 装饰物,等等先别急,我们应该先定义一个鞋子,帽子,手表的抽象父类 AbstractClothes 。 

其实抽象的父类有一个构造函数,构造函数里面的参数是抽象的人类,这里的用法很巧妙,这也是能够实现装饰功能的一个必不可少的步骤。
package com.user;

/**
 * 定义抽象装饰物
 * @author T
 *
 */
public abstract class AbstractClothes implements AbstractPerson {

	AbstractPerson abstractPerson ;

	public AbstractClothes( AbstractPerson abstractPerson ){
		this.abstractPerson = abstractPerson ;
	}

	@Override
	public void show() {
		abstractPerson.show();
	}

}

下面开始定义,帽子装饰物  Hat 类, 继承 AbstractClothes 类

package com.user;

/**
 * 帽子装饰物
 * @author T
 *
 */
public class Hat extends AbstractClothes {

	public Hat(AbstractPerson abstractPerson) {
		super(abstractPerson);
	}

	@Override
	public void show() {
		super.show();
	    say();
	}

	public void say(){
		System.out.println( "我展示一个帽子");
	}

}

定义鞋子装饰类 Shoes ,   继承 AbstractClothes 类

package com.user;

/**
 * 鞋子装饰物
 * @author T
 *
 */
public class Shoes extends AbstractClothes {

	public Shoes(AbstractPerson abstractPerson) {
		super(abstractPerson);
	}

	@Override
	public void show() {
		super.show();
	    say();
	}

	public void say(){
		System.out.println( "我展示一双鞋子");
	}
}

创建测试类 Test

package com.user;

public class Test {

	public static void main(String[] args) {

		//创建被装饰者
		Me me = new Me() ;

		//裸体的人被装饰了帽子 ,具有了展示帽子的能力
		Hat hat = new Hat( me ) ;

		// 带了帽子的人被装饰了鞋子,具有了展示鞋子的本领
		Shoes shoes = new Shoes( hat ) ;

		shoes.show();
	}
}

运行结果:

什么都没穿,我展示的是裸体
我展示一个帽子
我展示一双鞋子

装饰器模式的类图

在学习完了一个小例子之后,我们试着总结出装饰器模式的类图。

装饰器模式类图:

  • Component抽象构件角色:真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互。
  • ConcreteCompoent具体构建角色(真实对象):定义一个将要接收附加责任的类。
  • Decorator装饰角色:持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能。
  • ConcreteDecorate具体装饰角色:负责给构件对象增加新的功能。

装模式在Java I/O库中的应用

IO流实现细节:

  • Component抽象构件角色:io流中的InputStream,OutputStream,Reader,Writer
  • ConcreteComponent具体构件角色:io流中的FileInputStream,FileOutputStream
  • Decorate装饰角色:持有抽象构件的引用,FilterInputStream,FilterOutputStream
  • ConcreteDecorate具体装饰角色:负责给构件对象添加新的责任,BufferedInputStream,BufferedOutputStream等

总结

  • 装饰模式(Decorate)也叫包装模式(Wrapper)
  • 装饰模式降低系统的耦合度,可以动态的增加或删除对象的责任,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。

优点

  •  扩展对象功能,比继承灵活,不会导致类个数急剧增加。
  • 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象。
  • 具体构 件 类和具体装饰类可以独立变化,用户可以根据需要自己增加新的 具体构件子类和具体装饰子类。

缺点

  • 产生很多小对象。大量小的对象占据内存,一定程度上影响性能。
  • 装饰模式易出错,调试排查比较麻烦。

参考资料:

Java设计模式学习09——装饰模式

Java与模式:装饰(Decorator)模式

时间: 2024-08-01 16:39:02

Java 装饰器模式详解的相关文章

深入理解JavaScript系列(29):设计模式之装饰者模式详解

 这篇文章主要介绍了深入理解JavaScript系列(29):设计模式之装饰者模式详解,装饰者用用于包装同接口的对象,不仅允许你向方法添加行为,而且还可以将方法设置成原始对象调用(例如装饰者的构造函数),需要的朋友可以参考下     介绍 装饰者提供比继承更有弹性的替代方案. 装饰者用用于包装同接口的对象,不仅允许你向方法添加行为,而且还可以将方法设置成原始对象调用(例如装饰者的构造函数). 装饰者用于通过重载方法的形式添加新功能,该模式可以在被装饰者前面或者后面加上自己的行为以达到特定的目的.

Java设计模式之装饰者模式详解和代码实例_java

装饰者模式可以给已经存在的对象动态的添加能力.下面,我将会用一个简单的例子来演示一下如何在程序当中使用装饰者模式. 1.装饰者模式 让我们来假设一下,你正在寻找一个女朋友.有很多来自不同国家的女孩,比如:美国,中国,日本,法国等等,他们每个人都有不一样的个性和兴趣爱好,如果需要在程序当中模拟这么一种情况的话,假设每一个女孩就是一个Java类的话,那么就会有成千上万的类,这样子就会造成类的膨胀,而且这样的设计的可扩展性会比较差.因为如果我们需要一个新的女孩,就需要创建一个新的Java类,这实际上也

JAVA 静态代理模式详解及实例应用_java

JAVA 静态代理模式 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问. 代理模式说白了就是"真实对象"的代表,在访问对象时引入一定程度的间接性,因为这种间接性可以附加多种用途. 在这实现代码之前,先讲一个简单的生活故事,我们都知道我们周边有很多公司有房屋买卖或租赁的业务,比如链家(LianJia),但链家本身是不存在任何实际房屋资产的,他所售卖租赁的房屋均需要房屋产权所有人(HomeMaster)提供,才得以实现公司的房源需求:同时公司要的卖房租房业务均需要公司

Python中的装饰器用法详解_python

本文实例讲述了Python中的装饰器用法.分享给大家供大家参考.具体分析如下: 这里还是先由stackoverflow上面的一个问题引起吧,如果使用如下的代码: 复制代码 代码如下: @makebold @makeitalic def say():    return "Hello" 打印出如下的输出: <b><i>Hello<i></b> 你会怎么做?最后给出的答案是: 复制代码 代码如下: def makebold(fn):    

Python中的装饰器用法详解

来源:http://www.jb51.net/article/59867.htm 来源:http://blog.csdn.net/mdl13412/article/details/22608283 这篇文章主要介绍了Python中的装饰器用法,以实例形式详细的分析了Python中的装饰器的使用技巧及相关注意事项,具有一定参考借鉴价值,需要的朋友可以参考下 本文实例讲述了Python中的装饰器用法.分享给大家供大家参考.具体分析如下: 这里还是先由stackoverflow上面的一个问题引起吧,如

decorator 装饰器模板 详解

要使用decorator标签需要下载sitemesh.jar包. decorator标签可以轻松解决页面布局的问题,轻松是因为相比<include>标签(需要在每个页面都用他引入JSP)而 言,decorator标签的使用很简便,只需要在配置文件decorators.xml进行相应的配置再加上一个装饰器(其实就是一个JSP页面)即 可. 加上强大的过滤器,你可以装饰何一个被打开的页面,而不用像以前一样加工每一个JSP页面. 装饰器例子: <excludes>   <patte

Python 中的闭包与装饰器的详解

闭包(closure)是函数式编程的重要的语法结构.闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性. 如果在一个内嵌函数里,对在外部函数内(但不是在全局作用域)的变量进行引用,那么内嵌函数就被认为是闭包(closure). 定义在外部函数内但由内部函数引用或者使用的变量称为自由变量. 总结一下,创建一个闭包必须满足以下几点: 1. 必须有一个内嵌函数 2. 内嵌函数必须引用外部函数中的变量 3. 外部函数的返回值必须是内嵌函数 ###1.闭包使用示例 先看一个闭包的例子:     I

JavaScript中的装饰者模式详解

一. 装饰者模式的定义 装饰者模式的定义:动态地给一个对象添加额外的职责,而不会影响从这个类派生的其他对象. 二. 装饰者模式的实现 装饰者模式能够在不改变对象自身的基础上,在程序运行期间给对象动态添加职责. 在JavaScript的实际实现中,可以将本体对象放到装饰者对象中,这些对象以一条链的方式进行引用,形成一个聚合对象.本体对象和装饰者对象都拥有相同的接口,当请求到达链中的装饰者对象,这个装饰者对象会执行自身,随后将请求转发给本体对象. 2.1 通过对象覆写来实现装饰者模式 代码如下: /

Java装饰器设计模式初探_java

本篇随笔主要介绍用Java实现简单的装饰器设计模式: 先来看一下装饰器设计模式的类图: 从图中可以看到,我们可以装饰Component接口的任何实现类,而这些实现类也包括了装饰器本身,装饰器本身也可以再被装饰. 下面是用Java实现的简单的装饰器设计模式,提供的是从基本的加入咖啡入手,可以继续加入牛奶,巧克力,糖的装饰器系统. interface Component { void method(); } class Coffee implements Component { @Override