Android开发经验谈Android开发Android技术知识

使用组合的设计模式——美颜相机中的装饰者模式

2019-06-13  本文已影响9人  唐子玄

这是设计模式系列的第二篇,系列文章目录如下:

  1. 一句话总结殊途同归的设计模式:工厂模式=?策略模式=?模版方法模式

  2. 使用组合的设计模式 —— 美颜相机中的装饰者模式

  3. 使用组合的设计模式 —— 找对象要用的远程代理模式

  4. 用设计模式去掉没必要的状态变量 —— 状态模式

几乎所有的设计模式都是通过增加一层抽象来解决问题。

上一篇中提到的三个设计模式通过相同的手段来达到相同的目的:它们通过接口和抽象方法来新增抽象层以应对变化。

这一系列的后续几篇中会提到的四个设计模式通过相同的手段来达到不同的目的:它们通过新增一个类并持有原有类的方式实现对其扩展或限制。

这一篇先来看看装饰者模式。

装饰者模式就好像美颜相机,通过添加不同的装饰品,它可以让你变成另一个你。(虽然可能面目全非,但本质上还是你)

只复用类型

假设有四种饰品:耳环、钻石、黄金、羽毛。不同装饰品有不同价格,通常我们会这样做抽象:

//抽象饰品
public abstract class Accessory {
    public abstract String name();//饰品名称
    public abstract int cost();//饰品价格
}

//耳环
public class Ring extends Accessory {
    @Override
    public String name() { return "Ring"; }
    @Override
    public int cost() { return 20; }
}

//钻石
public class Diamond extends Accessory {
    @Override
    public String name() { return "Diamond"; }
    @Override
    public int cost() { return 1000; }
}

//黄金
public class Gold extends Accessory {
    @Override
    public String name() { return "Gold"; }
    @Override
    public int cost() { return 300; }
}

//羽毛
public class Feather extends Accessory {
    @Override
    public String name() { return "Feather"; }
    @Override
    public int cost() { return 90; }
}

现推出两款新饰品:黄金耳环,羽毛黄金耳环。同样的思路,使用继承可以解决问题:

public class GoldRing extends Accessory {
    @Override
    public String name() { return "GoldRing"; }
    @Override
    public int cost() { return 320; }
}

public class FeatherGoldRing extends Accessory {
    @Override
    public String name() {  "FeatherGoldRing"; }
    @Override
    public int cost() { return 1110; }
}

有没有一种比继承更好的方案在现有饰品基础上扩展新的饰品?

既复用类型又复用行为

采用组合的方式就可以实现既复用类型又复用行为:

public class Gold extends Accessory {
    private Accessory accessory;
    public Gold(Accessory accessory) { this.accessory = accessory; }
    
    @Override
    public String name() {
        return "Gold " + accessory.name();
    }
    @Override
    public int cost() {
        return 300 + accessory.cost();
    }
}

public class Feather extends Accessory {
    private Accessory accessory;
    public Feather(Accessory accessory) { this.accessory = accessory; }

    @Override
    public String name() {
        return "Feather " + accessory.name();
    }
    @Override
    public int cost() {
        return 90 + accessory.cost();
    }
}

用组合的方式实现羽毛黄金耳环:

Accessory ring = new Gold(new Feather(new Ring()));
Accessory ring = new Gold(new Gold(new Feather(new Ring())));

抽象的装饰者?

新的需求来了:基础饰品镶嵌附加饰品收取 10% 的一次性加工费。我们可以为所有附加饰品增加一层抽象:

public abstract class Decorator extends Accessory{
    private Accessory accessory;
    public Decorator(Accessory accessory) { this.accessory = accessory; }

    @Override
    public int cost() {
        return  1.1 * accessory.cost();
    }
}
public class Gold extends Decorator {
    public Gold(Accessory accessory){ super(accessory); }

    @Override
    public String name() {
        return "Gold " + accessory.name();
    }
    @Override
    public int cost() {
        return 300 + super.cost();
    }
}

总结

运用组合的设计模式不止装饰者一个,该系列的后续文章会继续分析“组合”在设计模式中的运用。

推荐阅读

上一篇 下一篇

猜你喜欢

热点阅读