1、什么是装饰器模式?
装饰器模式的核心是要有一个共通接口,然后共通接口又分成两大类实现。一种实现是被修饰者,它实现接口的主体功能。另一种是修饰者,它相当于一个饰品的功能,不改变被修饰者的实现,只是在原有实现上再加上点“修饰”。最后是构建者,它负责将被修饰者与“饰品”就是修饰者组装起来。
装饰器模式涉及到的四个角色:
- 共通接口
- 被修饰者:它实现共通接口,是主体功能。
- 饰品:这也实现共通接口,但只实现“修饰”功能,主体功能调用构建器传入的被修饰者实现
- 构建者:它负责组合“被修饰者”与“饰品”
2、装饰器模式要点
在具体实践中,关键问题是分离“主体”与“饰品”。主题是必需有的功能,饰品是可有可无的功功能。一个主体可以不与任何饰品组合,也可以与多个饰品组合。组合的过程是在代码运行过程中实现的,不是在编译阶段,因此说它是“动态”的为已存在的类添加新功能。
修饰器虽然也实现了共通接口,但接口的主要功能是通过传入的被修饰者的实例实现的,它只是“增加”新额外的功能,不是重新实现被修饰者的实现。这样的话,无论是被修饰者,还是组装以后的结果,都可以当成共通接口使用,这个就是“透明”的增加新功能。
3、示例
假如我们实现一个小游戏,里边有很多小动物,这些小动物可以用任意的“饰品”打扮起来。
首先有共通接口Animal,然后分别从Animal实现猫与狗,这个是主体。再然后分别给Animal加上帽子与鞋子,这个是“饰品”。
代码如下:
package com.zhangxf.test;
// 动物的共通接口
interface Animal {
void say();
}
// 动物“猫”的实现主体
class Cat implements Animal{
public void say() {
System.out.println("I am class Cat");
}
}
// 动物“狗”的实现主体
class Dog implements Animal{
public void say() {
System.out.println("I am class Dog");
}
}
// 用“帽子”修饰动物
class AnimalWithHat implements Animal {
private Animal ani;
AnimalWithHat(Animal ani) {
this.ani = ani;
}
public void say() {
ani.say();
System.out.println("I hava a hat");
}
}
//用“鞋子”修饰动物
class AnimalWithShoes implements Animal {
private Animal ani;
AnimalWithShoes(Animal ani) {
this.ani = ani;
}
public void say() {
ani.say();
System.out.println("I hava shoes");
}
}
public class Decorator {
// main方法就是构建者
public static void main(String[] args) {
// 一般的猫
Animal cat = new Cat();
cat.say();
System.out.println("==========1==========");
// 般的狗
Animal dog = new Dog();
dog.say();
System.out.println("===========2=========");
// 戴帽子的猫
Animal catWithHat = new AnimalWithHat(cat);
catWithHat.say();
System.out.println("=========3===========");
// 穿鞋的猫
Animal catWithShoes = new AnimalWithShoes(cat);
catWithShoes.say();
System.out.println("==========4==========");
// 给戴帽子的猫穿上鞋
Animal catWithHatAndShoes = new AnimalWithShoes(catWithHat);
catWithHatAndShoes.say();
System.out.println("===========5=========");
// 给穿鞋的猫带上帽子
Animal catWithShoesAndHat = new AnimalWithHat(catWithShoes);
catWithShoesAndHat.say();
System.out.println("==========6==========");
// 戴帽子的狗
Animal dogWithHat = new AnimalWithHat(dog);
dogWithHat.say();
System.out.println("===========7=========");
// 穿鞋的狗
Animal dogWithShoes = new AnimalWithShoes(dog);
dogWithShoes.say();
System.out.println("==========8==========");
// 给戴帽子的狗穿上鞋
Animal dogWithHatAndShoes = new AnimalWithShoes(dogWithHat);
dogWithHatAndShoes.say();
System.out.println("===========9=========");
// 给穿鞋的狗带上帽子
Animal dogWithShoesAndHat = new AnimalWithHat(dogWithShoes);
dogWithShoesAndHat.say();
System.out.println("==========10==========");
}
}
输出如下:
I am class Cat
==========1==========
I am class Dog
===========2=========
I am class Cat
I hava a hat
=========3===========
I am class Cat
I hava shoes
==========4==========
I am class Cat
I hava a hat
I hava shoes
===========5=========
I am class Cat
I hava shoes
I hava a hat
==========6==========
I am class Dog
I hava a hat
===========7=========
I am class Dog
I hava shoes
==========8==========
I am class Dog
I hava a hat
I hava shoes
===========9=========
I am class Dog
I hava shoes
I hava a hat
==========10==========
可以看到,我们只是实现了两种具体的动物与饰品,却可以生成十个不同的组合。以后扩展的话,可以任意增加动物与饰品的各类。这两个东西起越多,产生的组合也就越多。