概述
- 可以实现动态(在编译期是固定的,但是在运行期是随着java程序运行的不同而变化的)地为一个对象增加新的功能;
- 使用组合或者聚合的形式代替继承的方式进行扩展新的功能, 这样就使整个功能模块更加灵活,很好的避免了新增功能使得类快速增多从而使整个软件类复杂度极高的情况。
- 装饰者模式就像一个牙膏的生产过程,有主体和外包装,主体可以单独存在并成为一个产品,主体也可以加上外包装使之成为一个新的主体也是一个产品。
参与角色
Component(抽象的主体角色):是主体对象和装饰者对象都要实现的接口或者继承的抽象类。这样,客户端就能够像调用具体的主体对象相同的方式去调用装饰者对象完成功能;
ConcreteComponent(具体的主体即被装饰者角色):就是一个用于被装饰的实体,也可以单独调用;
Decorator(抽象装饰者角色):一般为一个抽象类,也可以是实体类,它持有一个抽象主体的引用,并接收所有客户端的请求,并把这些请求转发给具体的被装饰者对象去处理,这样就能在具体被装饰者调用前后增加新的功能;
ConcreteDecorator(具体装饰者角色):负责给被装饰者扩展新的功能。
// 抽象主体, 面条
public abstract class Noodle {
// 面条的描述
public abstract String desc();
// 面条的价格
public abstract double cost();
}
// 具体的主体对象, 牛肉面
public class BeefNoodle extends Noodle {
public String desc() {
return "牛肉面";
}
public double cost() {
return 20.0;
}
}
// 抽象的装饰者,调料类, 需要实现主体的功能, 这样客户端才能像使用主体一样使用装饰者
public abstract class Seasoning extends Noodle {
// 持有被包装的主体对象
protected Noodle noodle;
public Seasoning(Noodle noodle) {
this.noodle = noodle;
}
}
// 具体的装饰者 鸡蛋,增加被装饰主体的 功能
public class Egg extends Seasoning {
public Egg(Noodle noodle) {
super(noodle);
}
//重新定义主体对外的功能
//具体装饰者对被装饰者对象实现增强新功能
public String desc() {
return "鸡蛋" + noodle.desc();
}
//重新定义主体对外的功能
//具体装饰者对被装饰者对象实现增强新功能
public double cost() {
return 2.0 + noodle.cost();
}
}
// 客户端使用
// 牛肉面
Noodle beefNoodle = new BeefNoodle();
// 加个鸡蛋, 变成鸡蛋牛肉面
beefNoodle = new Egg(beefNoodle);
// 对外使用依然是苗条
System.out.println(beefNoodle.desc());
System.out.println(beefNoodle.cost());
装饰者模式总结
- 装饰者模式(Decorator)也叫包装器模式(Wrapper)
它降低系统的耦合度,拥有可以动态的增加或删除对象的职责,并使得具体被装饰者类和具体装饰者类可以独立变化,以便扩展新的具体被装饰者类和具体装饰者类;
- 扩展对象功能,比继承灵活
- 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的可使用对象
装饰者模式和适配器模式的区别
- 适配器模式的意义是要将一个接口(或对象)转变成另一个接口功能的用途。
- 而装饰者模式不是要改变被装饰者对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能,或者改变原有对象的处理方式而提升性能。
- 适配器也可以在转换时增加新的职责,但主要目的不在此。装饰者模式主要是给被装饰者增加新职责的;