前言

今天学习装饰模式,这个模式在Android源码中很常见,记录一下相关知识,方便自己后续查阅和回顾。

demo根据参考文中写的。

正文

装饰模式

装饰模式(Decorator Pattern)是结构型的设计模式,它允许在运行时动态地向对象添加新的职责或功能,同时保持对象的原始类不变。

通过使用装饰器模式,可以在不修改现有代码的基础上扩展对象的功能,

优缺点

优点
  1. 采用装饰模式扩展对象的功能比采用继承方式更加灵活

  2. 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合

缺点
  1. 装饰模式增加了许多子类,如果过度使用会使程序变得很复杂

错误示范

不使用装饰者,扩展一个类的功能会使用继承方式来实现。

下面以煎饼果子为例

  1. 煎饼果子 (什么都不加的)

  2. 鸡蛋+煎饼果子

  3. 生菜+煎饼果子

  4. 生菜+鸡蛋+煎饼果子

/**
 * 煎饼果子
 */
public class Pancakes {
    public String name(){
        return "煎饼";
    }
    public double price(){
        return 4.0f;
    }
}
/**
 * 鸡蛋+煎饼果子
 */
public class EggPancakes extends Pancakes {
    public String name() {
        return "鸡蛋+" + super.name();
    }
    public double price() {
        return 4.0f + 1.0f;
    }
}
/**
 * 生菜+煎饼果子
 */
public class LettucePancakes extends Pancakes {

    public String name() {
        return "生菜+" + super.name();
    }
    public double price() {
        return super.price();
    }
}
/**
 * 生菜+鸡蛋+煎饼果子
 */
public class LettuceEggPancakes extends EggPancakes{
    public String name() {
        return "生菜+" + super.name();
    }
    public double price() {
        return super.price();
    }
}

如果要新增一个火腿肠选项呢?

比如,火腿肠,生菜火腿肠,鸡蛋火腿肠,鸡蛋生菜火腿肠,按照上面岂不是要新增4个类。

通过继承,需要创建多个类,而且还耦合度高,再新增一个鸡柳,类还会更多更复杂。

因此,需要使用装饰者模式。

主要角色

下面是装饰者主要角色

  1. 抽象构件(Component):

    定义一个抽象接口以规范准备接收附加责任的对象。

  2. 具体构件(Concrete Component):

    实现抽象构件,通过装饰角色为其添加一些职责。

  3. 抽象装饰(Decorator):

    继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。

  4. 具体装饰(ConcreteDecorator):

    实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

设计模式之装饰模式

demo

还是以煎饼果子为例,可以加鸡蛋,生菜,甚至还可以加火腿肠。

对比上面[错误示范]看看有啥区别。

抽象构件

抽象构件(Component),定义一个抽象接口以规范准备接收附加责任的对象。

定义一个饼,有名字和价钱两个抽象接口。

public abstract class Cakes {
    public abstract String name();
    public abstract double price();
}
具体构件

具体构件(Concrete Component),实现抽象构件,通过装饰角色为其添加一些职责。

也是需要装饰的对象,这里为煎饼果子,原汁原味的饼。

public class Pancakes extends Cakes {
    @Override
    public String name() {
        return "煎饼果子";
    }
    @Override
    public double price() {
        return 4.0f;
    }
}

每个人口味不一样,有人需要生菜,也有人需要鸡蛋,当然也有人两个多要(反正生菜免费)。

抽象装饰

继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。

public abstract class Decorator extends Cakes{
    Cakes cakes;
}

为抽象类,我们直接用父类Cakes的抽象类。

当然可以新增一些让子类实现的抽象方法,我们这里为了简单省略了。

具体装饰

实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

  1. 鸡蛋装饰的煎饼果子

/**
 * 鸡蛋+煎饼果子
 */
public class EggPancakes extends Decorator {
    public EggPancakes(Cakes cakes) {
        this.cakes = cakes;
    }
    @Override
    public String name() {
        return "鸡蛋+" + cakes.name();
    }
    @Override
    public double price() {
        return 1.0f + cakes.price();
    }
}
  1. 生菜装饰的煎饼果子

/**
 * 生菜+煎饼果子
 */
public class LettucePanCakes extends Decorator {
    public LettucePanCakes(Cakes cakes) {
        this.cakes = cakes;
    }

    @Override
    public String name() {
        return "生菜+" + cakes.name();
    }

    @Override
    public double price() {
        return cakes.price();
    }
}
  1. 火腿装饰的煎饼果子

/**
 * 火腿肠+ 煎饼果子
 */
public class HamPanCakes extends Decorator {
    public HamPanCakes(Cakes cakes) {
        this.cakes = cakes;
    }

    @Override
    public String name() {
        return "火腿肠+" + cakes.name();
    }

    @Override
    public double price() {
        return cakes.price()+ 2.0f;
    }
}
客户端
//煎饼果子
Pancakes pancakes = new Pancakes();
//鸡蛋+煎饼果子
EggPancakes eggPancakes = new EggPancakes(pancakes);
//生菜+鸡蛋+煎饼果子
LettucePanCakes lettuceEggPanCakes = new LettucePanCakes(eggPancakes);
//生菜+鸡蛋+火腿肠+煎饼果子
HamPanCakes hamLettuceEggPanCakes = new HamPanCakes(lettuceEggPanCakes);

打印结果

煎饼果子 --> 4.0
鸡蛋+煎饼果子 --> 5.0
生菜+鸡蛋+煎饼果子 --> 5.0
火腿肠+生菜+鸡蛋+煎饼果子 --> 7.0

相对[错误示范]的代码,使用装饰模式后类更少了,也更明了。

参考文章

  1. 设计模式之装饰模式(Decorator

  2. 23种设计模式之一— — — —装饰模式详细介绍与讲解

  3. 设计模式学习笔记(十二):装饰模式

  4. JAVA设计模式8:装饰模式,动态地将责任附加到对象上,扩展对象的功能

相关文章

暂无评论

none
暂无评论...