Android 设计模式

装饰者模式

2023-04-05  本文已影响0人  长点点

一、基本概念

装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象动态地添加新的功能,同时不改变其结构。它是继承的一种替代方案,可以实现在运行时动态地扩展对象的行为,而无需修改原有代码。

装饰者模式的主要角色有:
uml图
装饰者模式的优点有:
装饰者模式的缺点有:
装饰者模式的优化方法有:
装饰者模式和继承都可以用于扩展一个类的功能,但是它们有以下几点区别:
区别点 装饰者模式 继承
关系类型 动态的 静态的
关系性质 有一个 是一个
类的数量 可以减少 可能过多
封装性 可以保持 可能破坏
优点 实现开闭原则,灵活地增加功能,可以实现多重装饰,保持目标对象的封装性 实现代码复用,减少冗余代码,实现多态,提高程序的灵活性和可维护性,实现抽象化和封装化,提高程序的安全性和可读性
缺点 增加了系统的复杂性,可能导致调试困难,需要注意装饰顺序和装饰次数,可能与目标对象的接口不完全匹配 增加了系统的耦合度,降低了程序的灵活性和可扩展性,可能导致类层次过深或过宽,影响程序的结构和效率,可能破坏父类的封装性,暴露其内部细节和实现方式
使用场景 当需要动态地给一个对象增加额外的功能时;当需要给一个对象增加一些与其本身无关或与其它对象无关的功能时;当需要给一个对象增加多个功能,并且这些功能可以相互组合时 当需要表示“是一个”的关系时;当需要实现代码复用和多态时;当需要实现抽象化和封装化时

二、安卓源码中的实例

安卓源码中经常使用到装饰者模式,例如:

三、Kotlin、Java、C++实现

3.1 Kotlin实现

Kotlin是一种基于JVM的静态类型编程语言,它可以与Java互操作,并且支持函数式编程和面向对象编程的特性。Kotlin也可以用来实现装饰者模式,下面是一个简单的例子:

// 定义一个抽象组件,表示饮料
interface Beverage {
    // 返回饮料的描述
    fun getDescription(): String
    // 返回饮料的价格
    fun cost(): Double
}
// 定义一个具体组件,表示咖啡
class Coffee : Beverage {
    override fun getDescription(): String {
        return "咖啡"
    }

    override fun cost(): Double {
        return 10.0
    }
}
// 定义一个具体组件,表示茶
class Tea : Beverage {
    override fun getDescription(): String {
        return "茶"
    }

    override fun cost(): Double {
        return 5.0
    }
}
// 定义一个抽象装饰者,表示调料
abstract class CondimentDecorator(val beverage: Beverage) : Beverage {
    // 返回调料和饮料的描述
    override fun getDescription(): String {
        return "${beverage.getDescription()} + ${this.javaClass.simpleName}"
    }
}
// 定义一个具体装饰者,表示糖
class Sugar(beverage: Beverage) : CondimentDecorator(beverage) {
    // 返回糖和饮料的价格
    override fun cost(): Double {
        return beverage.cost() + 1.0
    }
}
// 定义一个具体装饰者,表示奶油
class Cream(beverage: Beverage) : CondimentDecorator(beverage) {
    // 返回奶油和饮料的价格
    override fun cost(): Double {
        return beverage.cost() + 2.0
    }
}
// 测试代码
fun main() {
    // 创建一个咖啡对象
    var coffee: Beverage = Coffee()
    println("${coffee.getDescription()} = ${coffee.cost()}")

    // 给咖啡加糖和奶油
    coffee = Sugar(coffee)
    coffee = Cream(coffee)
    println("${coffee.getDescription()} = ${coffee.cost()}")

    // 创建一个茶对象
    var tea: Beverage = Tea()
    println("${tea.getDescription()} = ${tea.cost()}")

    // 给茶加糖
    tea = Sugar(tea)
    println("${tea.getDescription()} = ${tea.cost()}")
}
// 输出结果
咖啡 = 10.0
咖啡 + Sugar + Cream = 13.0
茶 = 5.0
茶 + Sugar = 6.0

从上面的代码可以看出,Kotlin可以使用类和接口来实现装饰者模式,通过组合和委托的方式来给对象增加新的功能。Kotlin还有一些特性可以简化装饰者模式的实现,例如扩展函数和属性,委托属性等。

3.2 Java实现

Java是一种面向对象的编程语言,它也可以用来实现装饰者模式,下面是一个简单的例子:

// 定义一个抽象组件,表示饮料
public abstract class Beverage {
    // 返回饮料的描述
    public abstract String getDescription();
    // 返回饮料的价格
    public abstract double cost();
}
// 定义一个具体组件,表示咖啡
public class Coffee extends Beverage {
    @Override
    public String getDescription() {
        return "咖啡";
    }

    @Override
    public double cost() {
        return 10.0;
    }
}
// 定义一个具体组件,表示茶
public class Tea extends Beverage {
    @Override
    public String getDescription() {
        return "茶";
    }

    @Override
    public double cost() {
        return 5.0;
    }
}
// 定义一个抽象装饰者,表示调料
public abstract class CondimentDecorator extends Beverage {
    // 持有一个被装饰者的引用
    protected Beverage beverage;

    public CondimentDecorator(Beverage beverage) {
        this.beverage = beverage;
    }

    // 返回调料和饮料的描述
    @Override
    public String getDescription() {
        return beverage.getDescription() + " + " + this.getClass().getSimpleName();
    }
}
// 定义一个具体装饰者,表示糖
public class Sugar extends CondimentDecorator {

    public Sugar(Beverage beverage) {
        super(beverage);
    }

    // 返回糖和饮料的价格
    @Override
    public double cost() {
        return beverage.cost() + 1.0;
    }
}
// 定义一个具体装饰者,表示奶油
public class Cream extends CondimentDecorator {

    public Cream(Beverage beverage) {
        super(beverage);
    }

    // 返回奶油和饮料的价格
    @Override
    public double cost() {
        return beverage.cost() + 2.0;
    }
}
// 测试代码
public class Test {

    public static void main(String[] args) {
        // 创建一个咖啡对象
        Beverage coffee = new Coffee();
        System.out.println(coffee.getDescription() + " = " + coffee.cost());

        // 给咖啡加糖和奶油
        coffee = new Sugar(coffee);
        coffee = new Cream(coffee);
        System.out.println(coffee.getDescription() + " = " + coffee.cost());

        // 创建一个茶对象
        Beverage tea = new Tea();
        System.out.println(tea.getDescription() + " = " + tea.cost());

        // 给茶加糖
        tea = new Sugar(tea);
        System.out.println(tea.getDescription() + " = " + tea.cost());
    }
}
// 输出结果
咖啡 = 10.0
咖啡 + Sugar + Cream = 13.0
茶 = 5.0
茶 + Sugar = 6.0

从上面的代码可以看出,Java可以使用抽象类和接口来实现装饰者模式,通过继承和组合的方式来给对象增加新的功能。Java还有一些特性可以简化装饰者模式的实现,例如匿名内部类,Lambda表达式等。

3.3 C++实现

C++是一种面向对象的编程语言,它也可以用来实现装饰者模式,下面是一个简单的例子:

// 定义一个抽象组件,表示饮料
class Beverage {
public:
    // 返回饮料的描述
    virtual std::string getDescription() = 0;
    // 返回饮料的价格
    virtual double cost() = 0;
    // 虚析构函数,方便子类析构
    virtual ~Beverage() {}
};

// 定义一个具体组件,表示咖啡
class Coffee : public Beverage {
public:
    std::string getDescription() override {
        return "咖啡";
    }

    double cost() override {
        return 10.0;
    }
};

// 定义一个具体组件,表示茶
class Tea : public Beverage {
public:
    std::string getDescription() override {
        return "茶";
    }

    double cost() override {
        return 5.0;
    }
};

// 定义一个抽象装饰者,表示调料
class CondimentDecorator : public Beverage {
protected:
    // 持有一个被装饰者的指针
    Beverage* beverage;

public:
    CondimentDecorator(Beverage* beverage) : beverage(beverage) {}

    // 返回调料和饮料的描述
    std::string getDescription() override {
        return beverage->getDescription() + " + " + typeid(*this).name();
    }

    // 虚析构函数,释放被装饰者的内存
    virtual ~CondimentDecorator() {
        delete beverage;
    }
};

// 定义一个具体装饰者,表示糖
class Sugar : public CondimentDecorator {
public:
    Sugar(Beverage* beverage) : CondimentDecorator(beverage) {}

    // 返回糖和饮料的价格
    double cost() override {
        return beverage->cost() + 1.0;
    }
};

// 定义一个具体装饰者,表示奶油
class Cream : public CondimentDecorator {
public:
    Cream(Beverage* beverage) : CondimentDecorator(beverage) {}

    // 返回奶油和饮料的价格
    double cost() override {
        return beverage->cost() + 2.0;
    }
};
// 测试代码
int main() {
    // 创建一个咖啡对象
    Beverage* coffee = new Coffee();
    std::cout << coffee->getDescription() << " = " << coffee->cost() << std::endl;

    // 给咖啡加糖和奶油
    coffee = new Sugar(coffee);
    coffee = new Cream(coffee);
    std::cout << coffee->getDescription() << " = " << coffee->cost() << std::endl;

    // 创建一个茶对象
    Beverage* tea = new Tea();
    std::cout << tea->getDescription() << " = " << tea->cost() << std::endl;

    // 给茶加糖
    tea = new Sugar(tea);
    std::cout << tea->getDescription() << " = " << tea->cost() << std::endl;

    // 释放内存
    delete coffee;
    delete tea;

    return 0;
}
// 输出结果
咖啡 = 10
咖啡 + class Sugar + class Cream = 13
茶 = 5
茶 + class Sugar = 6

从上面的代码可以看出,C++可以使用类和虚函数来实现装饰者模式,通过继承和组合的方式来给对象增加新的功能。C++还有一些特性可以简化装饰者模式的实现,例如模板类,智能指针等。

四、优缺点、使用场景

4.1 优缺点

装饰者模式的优点有:

装饰者模式的缺点有:

4.2 使用场景

装饰者模式适用于以下场景:

五、和其他相似设计模式比较

设计模式 目的 使用场景 优点 缺点
装饰者模式 动态地扩展目标对象的功能 给组件添加样式或动画效果 实现开闭原则,灵活地增加功能 增加了子类的数量,可能增加复杂度
适配器模式 使不兼容的接口能够协作 封装第三方库或API 实现接口转换,解决兼容问题 不能改变被适配对象的行为
代理模式 控制对目标对象的访问 实现缓存、拦截、验证等功能 实现访问控制,增加安全性和效率 可能降低目标对象的性能
上一篇下一篇

猜你喜欢

热点阅读