# 装饰者模式

今天在复习java的IO时，知道了Java的IO流使用了装饰器模式，它将IO流分成底层节点流和上层处理流。

## 1. 简介

装饰者模式(Decorator)的意图就是动态地给一个对象添加一些额外的职责。就新增功能来说，装饰者模式比生成子类更为灵活。有时，我们希望给每个对象而不是整个类添加一些功能，这个时候就需要用到装饰者模式了。

**装饰者模式具有以下特征：**

* 它必须具有一个装饰的对象；
* 它必须拥有与被装饰对象相同的接口；
* 它可以给被装饰的对象添加额外的功能；

总的来说就是：保持接口，增强性能。

## 2. 实例代码

现在我们用装饰者模式实现一个需求：当前系统下学生只有学习的能力，现在要给他增加运动和音乐的能力。

Person类

```java
package com.wangjun.designPattern.decorator;

public interface Person {
	public void function();
}
```

Student类

```java
package com.wangjun.designPattern.decorator;

public class Student implements Person {

	@Override
	public void function() {
		System.out.println("学生具有学习的能力。");
	}

}
```

装饰器1

```java
package com.wangjun.designPattern.decorator;

public class Decorator1 implements Person {
	
	private Person person;
	
	public Decorator1(Person person) {
		this.person = person;
	}

	@Override
	public void function() {
		System.out.println("装饰器1增加功能：体育能力。");
		person.function();
	}

}
```

装饰器2

```java
package com.wangjun.designPattern.decorator;

public class Decorator2 implements Person {
	
	private Person person;
	
	public Decorator2(Person person) {
		this.person = person;
	}

	@Override
	public void function() {
		System.out.println("装饰器2增加能力：音乐。");
		person.function();
	}

}
```

测试类

```java
package com.wangjun.designPattern.decorator;

public class App {
	public static void main(String[] args) {
		//原始对象
		Person person = new Student();
		
		//装饰类对象
		Person decorator = new Decorator2(new Decorator1(person));
		decorator.function();
	}
}
```

运行结果

```
装饰器2新增能力：音乐。
装饰器1增加功能：体育能力。
学生具有学习的能力。
```

从结果可以看出，使用装饰者模式增强了类的功能。

## 3. 装饰器模式与代理模式的区别

看到装饰器模式的功能和实现，很容易想到代理模式，也是这么实现的啊，功能类似。那这两种模式有什么区别呢？先来看一下两种模式的定义：

**装饰者模式：** 动态的将责任附加到被装饰者对象上，用于扩展对象的功能，是继承关系的替代方案。Java IO的设计即是装饰者模式的典型应用。

**代理模式：** 对其他对象进行代理，以控制对被代理对象的访问。Spring AOP是代理模型的一个典型应用。

二者的实现机制确实类似，可以看到两者的实现代码也有很多重复的地方。但是从作用上看，两种模式是相反的。其实设计模式的作用是为了让程序员更好的理解程序，在一个地方上写装饰模式，大家就知道你是在新增功能，在一个地方上写代理模式，大家就知道你是在控制对象的访问。

## 4. Java IO流实现装饰者模式


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jun-wang.gitbook.io/learnjava/ji-shu-xue-xi/java-she-ji-mo-shi/zhuang-shi-zhe-mo-shi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
