我们都知道,可以使用两种方式给一个类或者对象添加行为。
一是使用继承。继承是给一个类添加行为的比较有效的途径。通过使用继承,可以使得子类在拥有自身方法的同时,还可以拥有父类的方法。但是使用继承是静态的,在编译的时候就已经决定了子类的行为,我们不便于控制增加行为的方式和时机。
二是使用关联。组合即将一个对象嵌入到另一个对象中,由另一个对象来决定是否引用该对象来扩展自己的行为。这是一种动态的方式,我们可以在应用程序中动态的控制。
与继承相比,关联关系的优势就在于不会破坏类的封装性,且具有较好的松耦合性,可以使系统更加容易维护。但是它的缺点就在于要创建比继承更多的对象
一、装饰者的定义:
装饰着模式动态的将责任附加到对象上,若想要扩展功能,装饰着提供比继承更有弹性的替代方案。
二、装饰着模式的UML图:
Compoent类:抽象类,每个组件可以单独使用它,或者包装起来使用
ConcreteCompoent类:动态加载新行为的对象,继承于Compoent
Decorator类:装饰着共同实现的接口,可以使抽象类
ConcreteDecorator1、ConcreteDecorator2类:装饰实例,装饰者包着Compent
三、应用场景:
Startbuzz是以扩张速度最快的的咖啡连锁店。因为扩张太快,他们准备更新订单系统,以供应需求,他们原先的设计是这样的。
购买咖啡时,可以要求在其中加入各种调料,例如:牛奶(Milk)、豆浆(Soy)、摩卡(Mocha)。Startbuzz会根据不同的调料收取不同的费用,所以订单必须考虑到调料部分。。
这是他们的第一次尝试。。。
解决方案:
四、编写代码
Compotemt:Beverage类
//@file:beverage.java public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription(){ return description; } public abstract double cost(); }
ConcreteCompotemt:Espresso类
//浓缩咖啡 //@file:Espresso.java public class Espresso extends Beverage { <span style="white-space:pre"> </span>public Espresso(){ description = "Espresso"; } @Override public double cost() { return 1; } }CondimentDecorator:HouseBlend类
//@file:HouseBlend.java 、 //深烤烘焙 public class HouseBlend extends Beverage { public HouseBlend(){ description = "HouseBlend"; } @Override public double cost() { return 0.5; } }Decorator:CondimentDecorator类
//@file:CondimentDecorator.java public abstract class CondimentDecorator extends Beverage{ abstract public String getDescription(); }
ConcreteDecorator:Milk类
//file:Milk.java 牛奶味道的调料 public class Milk extends CondimentDecorator { Beverage beverage; public Milk(Beverage beverage){ this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription()+"-Milk"; } @Override public double cost() { return beverage.cost()+2.0; } }
ConcreteDecorator:Mocha类
//摩卡味道的调料 public class Mocha extends CondimentDecorator { Beverage beverage; public Mocha(Beverage beverage){ this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription()+"-Mocha"; } @Override public double cost() { return beverage.cost()+3.0; } }
ConcreteCDecorator:Soy类
//豆浆味道的调料 public class Soy extends CondimentDecorator { Beverage beverage; public Soy(Beverage beverage){ this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription()+"-Soy"; } @Override public double cost() { return beverage.cost()+4.0; } }
开始下单啦!!!
public class OrderApp { public static void main(String[] args) { Beverage beverage1 = new HouseBlend(); beverage1 = new Milk(beverage1); beverage1 = new Mocha(beverage1); beverage1 = new Soy(beverage1); System.out.println("beverage1 description:"+beverage1.getDescription()+"\ncost:"+beverage1.cost()); Beverage beverage2 = new Espresso(); beverage2= new Milk(beverage2); beverage2 = new Mocha(beverage2); System.out.println("beverage2 description:"+beverage2.getDescription()+"\ncost:"+beverage2.cost()); } }
output:
beverage1 description:HouseBlend-Milk-Mocha-Soy
cost:9.5
beverage2 description:Espresso-Milk-Mocha
cost:6.0