java component 构造函数_[JAVA设计模式]-06-装饰模式

Java中常见的设计模式

Java 中的 23 种设计模式:

Factory(工厂模式)、Builder(建造模式)、Factory Method (工厂方法模式)、
Prototype(原始模型模式)、Singleton(单例模式)、Facade(门面模式)、
Adapter(适配器模式)、Bridge(桥梁模式)、 Composite(合成 模式)、
Decorator(装饰模式)、Flyweight(享元模式)、Proxy(代理模式)、
Command(命令模式)、 Interpreter(解释器模式)、Visitor(访问者模式)、
Iterator(迭代子模式)、 Mediator(调停者模式)、Memento(备忘录模式)、
Observer(观察者模式)、State(状态模式)、Strategy(策略模式)、 
Template Method(模板方法模式)、Chain Of Responsibleity(责任链模式) 

IO 流使用的是装饰者模式、按钮监听观察者模式、forEach 遍历 List TreeSet 使用策略模式

装饰模式

装饰模式(Decorator)也叫包装器模式(Wrapper)。GOF 在《设计模式》一书中给出的定义为:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。让我们来理解一下这句话。我们来设计“门”这个类。假设你根据需求为“门”类作了如下定义:

79fd2ec5da89fc52725f84552543e12b.png

现在,在系统的一个地方需要一个能够报警的Door,你来怎么做呢?你或许写一个Door 的子类 AlarmDoor,在里面添加一个子类独有的方法 alarm()。嗯,那在使用警报门的地方 你必须让客户知道使用的是警报门,不然无法使用这个独有的方法。而且,这个还违反了 Liskov 替换原则。 也许你要说,那就把这个方法添加到 Door 里面,这样不就统一了?但是这样所有的门都必须有警报,至少是个“哑巴”警报。而当你的系统仅仅在一两个地方使用了警报门,这明 显是不合理的——虽然可以使用缺省适配器来弥补一下。 这时候,你可以考虑采用装饰模式来给门动态的添加些额外的功能。

装饰着模式的组成:

  1. 抽象构件角色(Component):定义一个抽象接口,以规范准备接收附加责任的对象

2) 具体构件角色(Concrete Component):这是被装饰者,定义一个将要被装饰增加功能的类。

3) 装饰角色(Decorator):持有一个构件对象的实例,并定义了抽象构件定义的接口。

4) 具体装饰角色(Concrete Decorator):负责给构件添加增加的功能。

类图如下

c38d1dc5e5bc8e7788d60278d5bf863f.png

图中 ConcreteComponent 可能继承自其它的体系,而为了实现装饰模式,他还要实现 Component 接口。整个装饰模式的结构是按照组合模式来实现的——两者都有类似的结构 图,都基于递归组合来组织可变数目的对象。但是两者的目的是截然不同的,组合 (Composite)模式侧重通过递归组合构造类,使不同的对象、多重的对象可以“一视同仁”; 而装饰(Decorator)模式仅仅是借递归组合来达到定义中的目的

// 简单案例分析
class Person
{
	public void eat()
	{
		System.out.println("吃饭...");
	}
}
class newPerson extends Person
{
	public void eat()
	{
		System.out.println("饭前开胃酒...");
		super.eat();
		System.out.println("饭后甜点...");
		System.out.println("饭后休闲...");
	}
}
class newWrapperPerson
{
	/**
	 * 装饰者模式:
	 * 1.定义一个私有的装饰对象
	 * 2.提供一个带参数的构造函数初始化该对象
	 * 3.根据需求在原有功能的基础上扩展相应的功能
	 */
	private Person p;
	public newWrapperPerson(Person p)
	{
		this.p = p;
	}
	public void eat()
	{
		System.out.println("开始吃饭、聊天...喝喝小酒...");
		p.eat();
		System.out.println("饭后甜点...");
		System.out.println("饭后休闲...");
		System.out.println("吃饭结束...");
	}
}


public class WrapperDemo {
	/**
	 * 装饰者模式是为了解决给类的功能增强而出现的
	 *  --对Writer根据不同的业务进行划分
	 *  Writer
	 *  	 |------TextWriter
	 *  	 |------MediaWriter
	 *  	 |------ImageWriter
	 *  
	 *  ---随着业务功能的提升   这时需要对Writer再次改写 要求提升性能    --利用缓冲
	 *  Writer
	 *  	 |------TextWriter
	 *  				|----BufferedTextWriter
	 *  	 |------MediaWriter
	 *  				|---BufferedMediaWriter
	 *  	 |------ImageWriter
	 *  				|---BufferedImageWriter
	 *  
	 *  ---业务进一步提升需求  这时要求 对Writer 提高容错性和完整性   --- 利用差异传输...
	 *  Writer
	 *  	 |------TextWriter
	 *  				|----BufferedTextWriter
	 *  						|----InfoExceptionBufferedTextWrite
	 *  	 |------MediaWriter
	 *  				|---BufferedMediaWriter
	 *  						|---InfoExceptionBufferedMediaWriter
	 *  	 |------ImageWriter
	 *  				|---BufferedImageWriter
	 *  						|----InfoExceptionBufferedImageWriter
	 *  
	 *  可以利用装饰者模式 解决继承来实现功能增强的这种行为
	 *   Writer
	 *   	  |---TextWriter
	 *   	  |---MediaWriter
	 *   	  |---ImageWriter
	 *        |---BufferedWriter
	 *        |--InfoExceptionWriter
	 *        
	 *  class BufferedWriter extends Writer{
	 *    private   TextWriter textWriter;
	 *    public  BufferedWriter( TextWriter textWriter){
	 *      this.textWriter=textWriter;
	 *    }
	 *  }
	 *  
	 *  使用装饰者模式的 特点: 
	 *  1.装饰者中的构造函数 必须接受被装饰的类
	 *  2.装饰的类和被装饰的类应该属于同一个体系
	 */
	public static void main(String[] args) {
		newWrapperPerson nwp = new newWrapperPerson(new Person());
		nwp.eat();
	}
}

GOF 书中给出了以下使用情况:

1) 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

2) 处理那些可以撤消的职责。

3) 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类 定义被隐藏,或类定义不能用于生成子类。

透明和半透明:

对于面向接口编程,应该尽量使客户程序不知道具体的类型,而应该对一个接口操作。 这样就要求装饰角色和具体装饰角色要满足 Liskov 替换原则。像下面这样:

Component c = new ConcreteComponent(); Component c1 = new ConcreteDecorator(c);

JUnit 中就属于这种应用,这种方式被称为透明式。而在实际应用中,比如 http://java.io 中往往因为要对原有接口做太多的扩展而需要公开新的方法(这也是为了重用)。所以往往不能对客户程序隐瞒具体的类型。这种方式称为“半透明式”。 在 http://java.io 中,并不是纯装饰模式的范例,它是装饰模式、适配器模式的混合使用。

采用 Decorator 模式进行系统设计往往会产生许多看上去类似的小对象,这些对象仅仅 在他们相互连接的方式上有所不同,而不是它们的类或是它们的属性值有所不同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值