装饰器模式

装饰器模式

装饰器模式就是动态地给一个对象添加一些额外的职责,扩展对象的功能.对于增加功能来说,装饰器模式比生成子类更为灵活.

装饰器模式的结构

通常来说,给一个对象添加一些额外的功能,可以通过继承来实现,但是这并不能动态地给对象添加职责,如果要添加一些职责,只能改变原有对象. 这时候就需要有装饰器模式出现了. 装饰器模式并不是利用继承和多态来扩展和复用功能,是基于对象组合的方式 .

装饰器模式的角色有:

  1. 抽象的对象角色 给出一个抽象接口,以规范准备接受附加功能的对象
  2. 具体的被装饰者 一个将要接受附加功能的具体实现,就是被装饰者,需要实现抽象的对象接口
  3. 装饰抽象类  持有一个被装饰者的实例,并实现抽象对象接口,为具体的装饰功能提供一个统一的接口
  4. 具体装饰角色 就是具体的装饰对象,继承子装饰抽象类,是用来给被装饰者添加附加功能的.

看类图:

装饰对象和被装饰对象实现的都是同一个接口,装饰对象也可以是一个接口,下面还可以有更多的具体的装饰对象.通过调用一个方法来装饰被装饰对象,以此来添加新的功能附件.

实例

比如我们现在要实现一个给人动态添加服装的功能.
首先定义一个接口,就是被装饰者实现的接口 里面有一个方法就是为人动态添加衣服

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class Person {
private String name ;
private String sex;
protected String getSex() {
return sex;
}
protected void setSex(String sex) {
this.sex = sex;
}
protected String getName() {
return name;
}
protected void setName(String name) {
this.name = name;
}

public abstract void show();
}

接着实现具体要穿衣服的人

1
2
3
4
5
6
7
8
9
10
11
12
public class Man extends Person {

public Man(String name, String sex) {
super.setName(name);
super.setSex(sex);
}

@Override
public void show() {
System.out.println("装扮"+getName()+getSex());
}
}

在实现装饰抽象类 定义一个统一的装饰接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public abstract class Decorator extends Person {
protected Person person;

public void decorator(Person person){
this.person = person;
}

@Override
public void show() {
if(person != null){
person.show();
}
}
}

具体装饰实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TShirts extends Decorator {
@Override
public void show() {
System.out.println("穿T恤");
super.show();
}
}
public class Shorts extends Decorator {
@Override
public void show() {
System.out.println("穿短裤");
super.show();
}
}

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test {
public static void main(String[] args) {
Person man = new Man("spj","男");
TShirts shirts = new TShirts();
Shorts shorts = new Shorts();
shirts.decorator(man);
shorts.decorator(shirts);
shirts.show();

}
}
输出:
穿短裤
穿T恤
装扮spj男

这个例子中每一个装饰对象都会调用自己装饰的那个对象,这个样子其实有点像责任链模式,不过责任链是将消息传递出去,而装饰模式是修饰已经已有的对象,一层一层的装饰.为对象动态的添加功能,最后形成一个完整的有用的对象.

在java中 输出输入流就是使用到了装饰器模式,在java中我们经常能见到这种写法.比如:

1
2
3
InputStream in = new FileInputStream("文件1");
BufferedInputStream bfi = new BufferedInputStream(in);
DataInputStream dis = new DataInputStream(bfi);

在这中写法中应该能够看出来这就是应用了装饰器模式,所有的这些输入流都继承InputStream类,通过一层一层的包装,来为输入流添加不同的功能.而他们每个类都有着上一层的一个实例对象,通过对此实例对象进行包装,就能够添加想要的功能.