一般来说装饰者模式有下面几个参与者:
Component:装饰者和被装饰者共同的父类,是一个接口或者抽象类,用来定义基本行为
ConcreteComponent:定义具体对象,即被装饰者
Decorator:抽象装饰者,继承自Component,从外类来扩展ConcreteComponent。对于ConcreteComponent来说,不需要知道Decorator的存在,Decorator是一个接口或抽象类
ConcreteDecorator:具体装饰者,用于扩展ConcreteComponent
注:装饰者和被装饰者对象有相同的超类型,因为装饰者和被装饰者必须是一样的类型,这里利用继承是为了达到类型匹配,而不是利用继承获得行为。
利用继承设计子类,只能在编译时静态决定,并且所有子类都会继承相同的行为;利用组合的做法扩展对象,就可以在运行时动态的进行扩展。装饰者模式遵循开放-关闭原则:类应该对扩展开放,对修改关闭。利用装饰者,我们可以实现新的装饰者增加新的行为而不用修改现有代码,而如果单纯依赖继承,每当需要新行为时,还得修改现有的代码。
example:
/**
* @author yaoshw
*/
public class TestMyIdea {
public static void main(String[] args) {
//不添加任何调料的饮料A
Beverage beverage = new APart();
System.out.println("Apart:" + beverage.getDescription() + "," + beverage.cost());
//添加摩卡调料的饮料B
Beverage beverage1 = new Mocha(new BPart());
System.out.println("Bpart:" + beverage1.getDescription() + "," + beverage1.cost());
//添加双份摩卡的饮料C
Beverage beverage2 = new Mocha(new Mocha(new CPart()));
System.out.println("Cpart:" + beverage2.getDescription() + "," + beverage2.cost());
//添加一份摩卡、一份豆浆的饮料D
Beverage beverage3 = new Soy(new Mocha(new DPart()));
System.out.println("Dpart:" + beverage3.getDescription() + "," + beverage3.cost());
}
}
/**
* 抽象类,相当于Component:cost方法和getDescription方法
*/
abstract class Beverage {
String description = "UnKnownBeverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
abstract class CondimentDerector extends Beverage {
@Override
public abstract String getDescription();
}
/**
* 具体装饰者:摩卡
*/
class Mocha extends CondimentDerector {
/**
* 保留基类的引用,以便于组合装饰者行为
*/
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return beverage.cost() + 2;
}
@Override
public String getDescription() {
return beverage.getDescription() + ",monka";
}
}
/**
* 具体装饰者:豆浆
*/
class Soy extends CondimentDerector {
Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return beverage.cost() + 3;
}
@Override
public String getDescription() {
return beverage.getDescription() + "soy";
}
}
/**
* 调料A
*/
class APart extends Beverage {
public APart() {
description = "Apart";
}
@Override
public double cost() {
return 19.5;
}
}
/**
* 调料B
*/
class BPart extends Beverage {
public BPart() {
description = "Bpart";
}
@Override
public double cost() {
return 20.5;
}
}
/**
* 调料C
*/
class CPart extends Beverage {
public CPart() {
description = "Cpart";
}
@Override
public double cost() {
return 21.5;
}
}
/**
* 调料D
*/
class DPart extends Beverage {
public DPart() {
description = "Dpart";
}
@Override
public double cost() {
return 22.5;
}
}