Component是基础接口
ConcreteComponent是Component的具体实现类,也就是等等要装饰的类
Decorator是装饰类,它实现Component,并且内部维护一个Component,可以使用构造方法来进行初始化
剩下的就是具体的装饰了
装饰模式,也叫包装模式。说白了,装饰就是用来替代继承的一个方案(比如Java中的BufferedReader就是),他可以在原来的功能的基础上增加一些功能。
来一个具体的,简单的例子
/**
* 基础接口
* @author BarryLee
* @2018年10月26日@下午8:53:53
*/
public interface Car {
/**
* 最基本的方法--可以跑
*/
public abstract void run();
/**
* 展示当前的所有功能
*/
public abstract void show();
}
/**
* 具体实现类,等等要装饰的一个类,实现Car的一个类
* @author BarryLee
* @2018年10月26日@下午8:54:17
*/
public class RunCar implements Car{
@Override
public void run() {
System.out.println("跑");
}
@Override
public void show() {
this.run();
}
}
/**
* 装饰类
* @author BarryLee
* @2018年10月26日@下午9:59:19
*/
public class CarDecorator implements Car{
private Car car ;
public CarDecorator(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public void run() {
car.run();
}
@Override
public void show() {
car.show();
}
}
/**
* 具体装饰类1
* @author BarryLee
* @2018年10月26日@下午9:59:28
*/
public class FlyCarDeco extends CarDecorator{
public FlyCarDeco(Car car) {
super(car);
}
@Override
public void run() {
super.getCar().run();
}
public void fly() {
System.out.println("可以飞");
}
@Override
public void show() {
super.getCar().show();
this.fly();
}
}
/**
* 具体装饰类2
* @author BarryLee
* @2018年10月26日@下午9:59:42
*/
public class SwimCarDeco extends CarDecorator{
public SwimCarDeco(Car car) {
super(car);
}
public void swim() {
System.out.println("可以游");
}
@Override
public void show() {
super.getCar().show();
this.swim();
}
@Override
public void run() {
System.out.println("跑");
}
}
/**
* 测试
* @author BarryLee
* @2018年10月26日@下午10:00:00
*/
public class TestDecorator {
@Test
public void test() {
Car car = new RunCar();
car.show();//跑
}
@Test
public void test1() {
Car car = new RunCar();
Car flyCar = new FlyCarDeco(car);
flyCar.show();
/*
跑
可以飞
*/
}
@Test
public void test2() {
Car car = new RunCar();
Car flyCar = new FlyCarDeco(car);
flyCar.show();
System.out.println("-----");
Car swimFlyCar = new SwimCarDeco(flyCar);
swimFlyCar.show();
/*
跑
可以飞
-----
跑
可以飞
可以游
*/
}
}
/2019.9.22更新//
下面是Head First 设计模式中的例子
需求是,一个咖啡店,有很多中咖啡,每种咖啡可以搭配不同的调料,要算出价格,同时有一个描述
package cn.bl.decorator.brverage;
/**
* @Deacription 这是咖啡店,也是测试代码
* @Author BarryLee
* @Date 2019/9/22 17:05
*/
public class Main {
public static void main(String[] args) {
Beverage b1 = new Espresso();
System.out.println(b1.getDescription() + ": " + b1.cost());
Beverage b2 = new HouseBlend();
b2 = new Mocha(b2);
b2 = new Whip(b2);
System.out.println(b2.getDescription() + ": " + b2.cost());
}
}
package cn.bl.decorator.brverage;
/**
* @Deacription 饮料抽象类,相当于Conponent
* @Author BarryLee
* @Date 2019/9/22 17:10
*/
public abstract class Beverage {
String description = "Unknown description";
public String getDescription() {
return description;
}
public abstract double cost();
}
package cn.bl.decorator.brverage;
/**
* @Deacription 浓缩咖啡,饮料的具体实现,相当于ConcreteComponent
* @Author BarryLee
* @Date 2019/9/22 17:21
*/
public class Espresso extends Beverage {
/**
* 构造器,设置饮料的描述
* description来自beverage
*/
public Espresso() {
description = "espresso coffee";
}
/**
* 返回Espresso的价格
* @return
*/
@Override
public double cost() {
return 1.99;
}
}
package cn.bl.decorator.brverage;
/**
* @Deacription 混合咖啡,相当于ConcreteComponent
* @Author BarryLee
* @Date 2019/9/22 17:28
*/
public class HouseBlend extends Beverage{
public HouseBlend() {
description = "house blend coffee";
}
@Override
public double cost() {
return .89;
}
}
package cn.bl.decorator.brverage;
/**
* @Deacription 调料抽象类,也就是装饰者,相当于类图中的Decorator
* 有抽象方法一定就是抽象类
*
* 首先,必须让Condiment Decorator能够取代Beverage
* 所以将CondimentDecorator拓展自Beverage
*
* @Author BarryLee
* @Date 2019/9/22 17:12
*/
public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();
}
package cn.bl.decorator.brverage;
/**
* @Deacription 摩卡调料,是一个具体的装饰者,所以它拓展自CondimentDecorator,相当于ConcreteDecorator
* @Author BarryLee
* @Date 2019/9/22 22:57
*/
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() + .20;
}
}
package cn.bl.decorator.brverage;
/**
* @Deacription 泡泡调料,相当于ConcreteDecorator
* @Author BarryLee
* @Date 2019/9/22 23:12
*/
public class Whip extends CondimentDecorator{
Beverage beverage;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", whip";
}
@Override
public double cost() {
return beverage.cost() + .22;
}
}
执行结果是
espresso coffee: 1.99
house blend coffee, mocha, whip: 1.31