结构型-装饰模式 Link to heading

装饰模式就像其名字一样,为了对现有的类进行装饰。比如一张相片就一张纸,如果直接贴在墙上,总感觉少了点什么,但是我们给其添加一个好看的相框,就会变得非常对味。装饰模式的核心就在于不改变一个对象本身功能的基础上,给对象添加额外的行为,并且它是通过组合的形式完成的,而不是传统的继承关系。

比如我们现在有一个普通的功能类:

public abstract class Base {   //顶层抽象类,定义了一个test方法执行业务
    public abstract void test();
}


public class BaseImpl extends Base{
    @Override
    public void test() {
        System.out.println("我是业务方法");   //具体的业务方法
    }
}

不过现在的实现类太单调了,我们来添加一点装饰上去:

public class Decorator extends Base{   //装饰者需要将装饰目标组合到类中

    protected Base base;

    public Decorator(Base base) {
        this.base = base;
    }

    @Override
    public void test() {
        base.test();    //这里暂时还是使用目标的原本方法实现
    }
}

public class DecoratorImpl extends Decorator{   //装饰实现

    public DecoratorImpl(Base base) {
        super(base);
    }

    @Override
    public void test() {    //对原本的方法进行装饰,我们可以在前后都去添加额外操作
        System.out.println("装饰方法:我是操作前逻辑");
        super.test();
        System.out.println("装饰方法:我是操作后逻辑");
    }
}

这样,我们就通过装饰模式对类的功能进行了扩展:

public static void main(String[] args) {
    Base base = new BaseImpl();
    Decorator decorator = new DecoratorImpl(base);  //将Base实现装饰一下
    Decorator outer = new DecoratorImpl(decorator);  //装饰者还可以嵌套

    decorator.test();

    outer.test();
}

场景模拟 Link to heading

设计一个系统,其中包含n种咖啡,咖啡中还可以加入各种配料。

Beverage 抽象类

public abstract class Beverage {
    // 每种饮料的描述:“名称,配料1,配料2...”
    String description = "Unknown Beverage";
  
    public String getDescription() {
        return description;
    }
  
    // 每种类型饮料的价格不同,故定义为抽象方法
    public abstract double cost();
}

几种具体咖啡

// DarkRoast
public class DarkRoast extends Beverage {
    public DarkRoast() {
        description = "Dark Roast";
    }

    @Override
    public double cost() {
        return .99;
    }
}


// Espresso
public class Espresso extends Beverage {
    public Espresso() {
        description = "Espresso";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}

配料表CondimentDecorator抽象类

public abstract class CondimentDecorator extends Beverage {
    // 因为每种配料对饮料的描述进行了附加的说明,所以每种饮料添加配料后,都需要重写 getDescription方法。
    @Override
    public abstract String getDescription();
}

具体配料

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() + .10;
    }
}


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;
    }
}

测试

制作一款DarkRoast,并加入两份mocha,一份milk

Beverage darkRoast = new DarkRoast();
darkRoast = new Mocha(darkRoast);
darkRoast = new Mocha(darkRoast);
darkRoast = new Milk(darkRoast);