装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。
介绍
意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
何时使用:在不想增加很多子类的情况下扩展类。
如何解决:将具体功能职责划分,同时继承装饰者模式。
关键代码: 1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
应用实例: 1、孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。 2、不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。
注意事项:可代替继承。
Old
package com.tzy.Decorator.com.old; /** * @author Heaton * @date 2018/5/7 21:36 * @describe 潜水车 */ public class SwimCar implements Car{ public void run() { System.out.println("潜水车跑起来"); } public void Swim() { System.out.println("潜水车游起来"); } public void show() { this.run(); this.Swim(); } }
package com.tzy.Decorator.com.old; /** * @author Heaton * @date 2018/5/7 21:35 * @describe 飞车 */ public class FlyCar implements Car { public void show() { this.run(); this.fly(); } public void run() { System.out.println("飞车跑起来"); } public void fly() { System.out.println("飞车飞起来"); } }
package com.tzy.Decorator.com.old; /** * @author Heaton * @date 2018/5/7 21:36 * @describe 跑车 */ public class RunCar implements Car { public void run() { System.out.println("跑车跑起来"); } public void show() { this.run(); } }
package com.tzy.Decorator.com.old; /** * @author Heaton * @date 2018/5/7 21:36 * @describe 潜水车 */ public class SwimCar implements Car{ public void run() { System.out.println("潜水车跑起来"); } public void Swim() { System.out.println("潜水车游起来"); } public void show() { this.run(); this.Swim(); } }
package com.tzy.Decorator.com.old; public class MainClass { public static void main(String[] args) { Car flycar = new FlyCar(); flycar.show(); Car swimCar = new SwimCar(); swimCar.show(); Car runCar = new RunCar(); runCar.show(); } }
News
拿引用 添加新功能
package com.tzy.Decorator.com.news; /** * @author Heaton * @date 2018/5/7 21:35 * @describe 车接口 */ public interface Car { public void show(); public void run(); }
package com.tzy.Decorator.com.news; /** * @author Heaton * @date 2018/5/7 21:43 * @describe Car装饰器 */ public abstract class CarDecorator implements Car{ private Car car; public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } public CarDecorator(Car car) { this.car = car; } public abstract void show(); }
package com.tzy.Decorator.com.news; public class FlyCarDecorator extends CarDecorator{ public FlyCarDecorator(Car car) { super(car); } public void show() { this.getCar().show(); this.fly(); } public void fly() { System.out.println("装配飞功能"); } public void run() { } }
package com.tzy.Decorator.com.news; public class SwimCarDecorator extends CarDecorator { public SwimCarDecorator(Car car) { super(car); } public void show() { this.getCar().show(); this.swim(); } public void swim() { System.out.println("装配潜水功能"); } public void run() { } }
package com.tzy.Decorator.com.news; /** * @author Heaton * @date 2018/5/7 21:36 * @describe 跑车 */ public class RunCar implements Car { public void run() { System.out.println("跑车跑起来"); } public void show() { this.run(); } }
package com.tzy.Decorator.com.news; public class MainClass { public static void main(String[] args) { Car car = new RunCar(); car.show(); System.out.println("---------"); Car swimcar = new SwimCarDecorator(car); swimcar.show(); System.out.println("---------"); Car flySwimCar = new FlyCarDecorator(swimcar); flySwimCar.show(); } }
******************demo 咖啡馆
先来个抽象的喝的东西
package com.tzy.Decorator.com.demo.coffeebar; /** * @author Heaton * @date 2018/5/11 21:20 * @describe 喝的饮料 */ public abstract class Drink { public String description=""; private float price=0f; public void setDescription(String description) { this.description=description; } public String getDescription() { return description+"-"+this.getPrice(); } public float getPrice() { return price; } public void setPrice(float price) { this.price=price; } //花费 public abstract float cost(); }
咖啡能喝
package com.tzy.Decorator.com.demo.coffeebar.coffee; import com.tzy.Decorator.com.demo.coffeebar.Drink; public class Coffee extends Drink { @Override public float cost() { return super.getPrice(); } }
扩展咖啡
package com.tzy.Decorator.com.demo.coffeebar.coffee; /** * @author Heaton * @date 2018/5/11 21:24 * @describe 无咖啡因咖啡 */ public class Decaf extends Coffee { public Decaf() { super.setDescription("Decaf"); super.setPrice(3.0f); } }
package com.tzy.Decorator.com.demo.coffeebar.coffee; /** * @author Heaton * @date 2018/5/11 21:26 * @describe 浓咖啡 */ public class Espresso extends Coffee{ public Espresso() { super.setDescription("Espresso"); super.setPrice(4.0f); } }
package com.tzy.Decorator.com.demo.coffeebar.coffee; /** * @author Heaton * @date 2018/5/11 21:24 * @describe 长黑咖啡 */ public class LongBlack extends Coffee{ public LongBlack() { super.setDescription("LongBlack"); super.setPrice(6.0f); } }
package com.tzy.Decorator.com.demo.coffeebar.coffee; /** * @author Heaton * @date 2018/5/11 21:25 * @describe 短黑咖啡 */ public class ShortBlack extends Coffee{ public ShortBlack() { super.setDescription("ShortBlack"); super.setPrice(5.0f); } }
需求来了,咖啡要加调料算计价格,那么来个装饰着,继承之前的喝的东西,然后在拿到喝的东西的引用来包装,本质还是喝的东西。
package com.tzy.Decorator.com.demo.coffeebar.decorator; import com.tzy.Decorator.com.demo.coffeebar.Drink; /** * @author Heaton * @date 2018/5/11 21:28 * @describe 装饰者中间层 */ public class Decorator extends Drink { private Drink Obj; public Decorator(Drink Obj){ this.Obj=Obj; }; @Override public float cost() { // 递归 return super.getPrice()+Obj.cost(); } @Override public String getDescription() { return super.description+"-"+super.getPrice()+"&&"+Obj.getDescription(); } }
具体实现
package com.tzy.Decorator.com.demo.coffeebar.decorator; import com.tzy.Decorator.com.demo.coffeebar.Drink; /** * @author Heaton * @date 2018/5/11 21:29 * @describe 加巧克力 */ public class Chocolate extends Decorator { public Chocolate(Drink Obj) { super(Obj); // TODO Auto-generated constructor stub super.setDescription("Chocolate"); super.setPrice(3.0f); } }
package com.tzy.Decorator.com.demo.coffeebar.decorator; import com.tzy.Decorator.com.demo.coffeebar.Drink; /** * @author Heaton * @date 2018/5/11 21:29 * @describe 加牛奶 */ public class Milk extends Decorator { public Milk(Drink Obj) { super(Obj); // TODO Auto-generated constructor stub super.setDescription("Milk"); super.setPrice(2.0f); } }
package com.tzy.Decorator.com.demo.coffeebar.decorator; import com.tzy.Decorator.com.demo.coffeebar.Drink; /** * @author Heaton * @date 2018/5/11 21:30 * @describe 加黄油咖啡 */ public class Soy extends Decorator { public Soy(Drink Obj) { super(Obj); // TODO Auto-generated constructor stub super.setDescription("Soy"); super.setPrice(1.5f); } }
测试
package com.tzy.Decorator.com.demo.coffeebar; import com.tzy.Decorator.com.demo.coffeebar.coffee.Decaf; import com.tzy.Decorator.com.demo.coffeebar.coffee.LongBlack; import com.tzy.Decorator.com.demo.coffeebar.decorator.Chocolate; import com.tzy.Decorator.com.demo.coffeebar.decorator.Milk; public class CoffeeBar { public static void main(String[] args) { Drink order; order=new Decaf(); System.out.println("order1 price:"+order.cost()); System.out.println("order1 desc:"+order.getDescription()); System.out.println("****************"); order=new LongBlack(); order=new Milk(order); order=new Chocolate(order); order=new Chocolate(order); System.out.println("order2 price:"+order.cost()); System.out.println("order2 desc:"+order.getDescription()); } }
装饰者模式:动态的将新功能附加到对象上,在对象功能拓展方面,它比继承更有弹性。