装饰者模式,是在不改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
装饰者模式中的角色:
(1) 被装饰者抽象Component,是一个接口或抽象类,就是定义最核心的对象,也是最原始的对象,这个类是需要装饰类的基类。
(2) 被装饰者具体实现ConcreteComponent,是Component类的一个实现类,要装饰的就是这个具体的实现类。
(3) 装饰者Decorator,一般是一个抽象类,实现接口或者抽象方法,它里面有个指向Component的引用,而且它还继承了被装饰者的抽象Component。
(4) 装饰者实现ConcreteDecorator,具体的装饰者类。
类图|:
代码实现:
被装饰者的抽象:
package com.demo.decorator.component;
/*
* 甜点类,被装饰者的抽象
*/
public abstract class Dessert {
protected String description = "Unknown Dessert";
/*
* 对甜点的描述,需要被装饰的方法
*/
public String getDescription() {
return description;
}
public Dessert() {
}
/*
* 甜点的价格,需要被装饰的方法
*/
public abstract double cost();
}
被装饰者的具体实现:
package com.demo.decorator.component;
/*
* 蛋糕类,被装饰者的具体实现
*/
public class Cake extends Dessert {
public Cake() {
description = "Cake";
}
@Override
public double cost() {
return 9.90;
}
}
package com.demo.decorator.component;
/*
* 面包类,被装饰者的具体实现
*/
public class Bread extends Dessert {
public Bread() {
description = "Bread";
}
@Override
public double cost() {
return 5.0;
}
}
装饰者的抽象:
package com.demo.decorator.decorator;
import com.demo.decorator.component.Dessert;
/*
* 佐料类,装饰者的抽象
*/
public abstract class CondimentDecorator extends Dessert {
/*
* 被装饰者的引用
*/
protected Dessert dessert;
public CondimentDecorator(Dessert dessert) {
this.dessert = dessert;
}
public abstract String getDescription();
public abstract double cost();
}
装饰者的具体实现:
package com.demo.decorator.decorator;
import com.demo.decorator.component.Dessert;
/*
* 巧克力类,装饰者的具体实现
*/
public class Chocolate extends CondimentDecorator {
public Chocolate(Dessert dessert) {
super(dessert);
}
/*
* 通过被装饰者的引用,扩展其方法的功能
*/
@Override
public String getDescription() {
return dessert.getDescription() + ", Chocolate";
}
/*
* 通过被装饰者的引用,扩展其方法的功能
*/
@Override
public double cost() {
return dessert.cost() + 1.0;
}
}
package com.demo.decorator.decorator;
import com.demo.decorator.component.Dessert;
/*
* 蓝莓类,装饰者的具体实现
*/
public class Blueberry extends CondimentDecorator {
public Blueberry(Dessert dessert) {
super(dessert);
}
/*
* 通过被装饰者的引用,扩展其方法的功能
*/
@Override
public String getDescription() {
return dessert.getDescription() + ", Blueberry";
}
/*
* 通过被装饰者的引用,扩展其方法的功能
*/
@Override
public double cost() {
return dessert.cost() + 1.5;
}
}
测试代码:
package com.demo.decorator;
import com.demo.decorator.component.Bread;
import com.demo.decorator.component.Cake;
import com.demo.decorator.component.Dessert;
import com.demo.decorator.decorator.Blueberry;
import com.demo.decorator.decorator.Chocolate;
public class MainApp {
public static void main(String[] args) {
/*
* 未被装饰的蛋糕
*/
Dessert cake = new Cake();
show(cake);
/*
* 被巧克力装饰的蛋糕
*/
Dessert chocolateCake = new Cake();
chocolateCake = new Chocolate(chocolateCake);
show(chocolateCake);
/*
* 被巧克力和蓝莓装饰的面包
* 被装饰者可以被多个装饰者装饰
*/
Dessert blueberryChocolateBread = new Bread();
blueberryChocolateBread = new Chocolate(blueberryChocolateBread);
blueberryChocolateBread = new Blueberry(blueberryChocolateBread);
show(blueberryChocolateBread);
}
public static void show(Dessert dessert) {
System.out.println(dessert.getDescription() +
" ¥" + dessert.cost());
}
}
结果输出:
Cake ¥9.9
Cake, Chocolate ¥10.9
Bread, Chocolate, Blueberry ¥7.5
使用装饰者模式的适用场合:
1) 当需要为某个现有的对象动态地增加一个新的功能或职责时,可以考虑使用装饰者模式;
2) 当某个对象的职责经常发生变化或者经常需要动态地增加职责,避免为了适应这样的变化而增加继承子类扩展的方式;