装饰器模式
装饰模式的用意是在不改变接口的前提下,增强所考虑的类的性能。
- 抽象组件:需要装饰的抽象对象(接口或抽象父类)
- 具体组件:需要装饰的对象
- 抽象装饰类:包含了对抽象组件的引用以及装饰着共有的方法
- 具体装饰类:被装饰的对象
抽象组件
interface Drink{
double cost();
String info();
}
具体组件
class Coffe implements Drink{
private String name = "原味咖啡";
public double cost(){
return 10;
}
public String info(){
return name;
}
}
抽象装饰类
abstract Decorate implements Drink{
// 对抽象组件的引用
private Drink drink;
public Decorate(Drink drink){
this.drink = drink;
}
public double cost(){
return this.drink.cost();
}
public String info(){
return this.drink.info();
}
}
具体装饰类
class Milk extends Decorate{
public Milk(Drink drink){
super(drink);
}
public double cost(){
return super.cost()*4;
}
public String info(){
return super.info()+"加入了牛奶";
}
}
class Suger extends Decorate{
public Suger(Drink drink){
super(drink);
}
public double cost(){
return super.cost()*2;
}
public String info(){
return super.info()+"加入了蔗糖";
}
}
Drink coffee = new Coffee();
// 装饰
Drink suger = new Suger(coffee);
System.out.println(suger.info()+"----"+suger.cost());// 原味咖啡加入了蔗糖----20.0
// 装饰
Drink milk = new Milk(suger);
System.out.println(milk.info()+"----"+milk.cost());// 原味咖啡加入了蔗糖加入了牛奶----80.0
以上new出来的对象都未进行向下转型,这是保证透明性
但是当需要在接口中新增方法时,这时候意味着需要向下转型,这时候就是半透明的装饰模式
Java IO InputStream就是半透明装饰器模式,
装饰模式优点:
- 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态决定 “贴上” 一个需要的 “装饰”,或者除掉一个不需要的 “装饰”。继承关系则不同,继承关系是静态的,它在系统运行前就决定了
- 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
缺点:
- 由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。