结构型模式-装饰模式

定义:

        装饰模式(Decorator Pattern)是一种比较常见的模式,其定义如下:Attach additional responsibilities to an object dynamically keeping the same interface.Decorators provide a flexible alternative to subclassing for extending functionality.(动态地给一个对象添加一些额外的职责。 就增加功能来说,装饰模式相比生成子类更为灵活。)

装饰模式通用类图

        装饰设计模式的核心思想是组合优于继承。它不通过继承父类来获取新功能,而是将对象的功能扩展逻辑封装在装饰器类中,通过组合的方式将装饰器与被装饰对象关联起来。这样,在运行时可以灵活地为对象添加、移除或替换装饰器,实现功能的动态变化,使代码更加灵活和可维护。

角色:

装饰模式包含以下几个核心角色:

1、抽象组件(Component)

        抽象组件定义了具体组件和装饰器的共同接口,它是被装饰对象和装饰器的抽象基类。客户端通过该接口与具体组件或被装饰后的组件进行交互,确保客户端可以一致地处理具体组件和装饰器。

2、具体组件(Concrete Component)

        具体组件是抽象组件的具体实现,它是被装饰的原始对象,实现了抽象组件定义的基本功能。

3、抽象装饰器(Decorator)

        抽象装饰器继承或实现了抽象组件接口,并且持有一个抽象组件类型的引用。它的主要作用是为具体装饰器提供一个通用的包装结构,在抽象装饰器中可以实现一些装饰器的通用行为,同时为具体装饰器扩展功能预留接口。

4、具体装饰器(Concrete Decorator)

        具体装饰器是抽象装饰器的具体实现类,它负责为被装饰对象添加具体的功能。每个具体装饰器都可以根据自身的逻辑,在调用被装饰对象的方法前后,添加额外的行为,从而实现功能的增强。​

代码示例:

        下面通过一个饮品制作示例来展示装饰设计模式的实现。假设我们有基础的饮品(如咖啡、茶),同时可以为饮品添加各种配料(如牛奶、糖、奶油),每种配料都会增加饮品的价格和描述信息。

(一)定义抽象组件

// 饮品抽象组件

public interface Beverage {

    String getDescription();

    double cost();

}

(二)定义具体组件

// 具体饮品:咖啡

public class Coffee implements Beverage {

    @Override

    public String getDescription() {

        return "咖啡";

    }



    @Override

    public double cost() {

        return 10.0;

    }

}

// 具体饮品:茶

public class Tea implements Beverage {

    @Override

    public String getDescription() {

        return "茶";

    }



    @Override

    public double cost() {

        return 8.0;

    }

}

(三)定义抽象装饰器

// 饮品装饰器抽象类

public abstract class BeverageDecorator implements Beverage {

    protected Beverage beverage;



    public BeverageDecorator(Beverage beverage) {

        this.beverage = beverage;

    }



    @Override

    public abstract String getDescription();



    @Override

    public abstract double cost();

}

(四)定义具体装饰器

// 具体装饰器:牛奶

public class Milk extends BeverageDecorator {

    public Milk(Beverage beverage) {

        super(beverage);

    }



    @Override

    public String getDescription() {

        return beverage.getDescription() + " + 牛奶";

    }



    @Override

    public double cost() {

        return beverage.cost() + 2.0;

    }

}

// 具体装饰器:糖

public class Sugar extends BeverageDecorator {

    public Sugar(Beverage beverage) {

        super(beverage);

    }



    @Override

    public String getDescription() {

        return beverage.getDescription() + " + 糖";

    }



    @Override

    public double cost() {

        return beverage.cost() + 1.0;

    }

}

// 具体装饰器:奶油

public class Cream extends BeverageDecorator {

    public Cream(Beverage beverage) {

        super(beverage);

    }



    @Override

    public String getDescription() {

        return beverage.getDescription() + " + 奶油";

    }



    @Override

    public double cost() {

        return beverage.cost() + 3.0;

    }

}

(五)客户端使用

public class DecoratorPatternClient {

    public static void main(String[] args) {

        // 创建一杯基础咖啡

        Beverage coffee = new Coffee();

        System.out.println(coffee.getDescription() + ",价格:" + coffee.cost() + "元");



        // 为咖啡添加牛奶和糖

        Beverage coffeeWithMilkAndSugar = new Sugar(new Milk(coffee));

        System.out.println(coffeeWithMilkAndSugar.getDescription() + ",价格:" + coffeeWithMilkAndSugar.cost() + "元");



        // 创建一杯基础茶,并添加奶油

        Beverage tea = new Tea();

        Beverage teaWithCream = new Cream(tea);

        System.out.println(teaWithCream.getDescription() + ",价格:" + teaWithCream.cost() + "元");

    }

}

优点 :

1、灵活扩展功能:可以在不修改原有对象代码的情况下,动态地为对象添加新功能,并且可以根据需要自由组合不同的装饰器,实现功能的多样化扩展。

2、遵循开闭原则:新增装饰器类不会影响到已有的代码,符合开闭原则,提高了代码的可维护性和可扩展性。

3、避免继承的局限性:相比于继承,装饰设计模式更加灵活,避免了因继承导致的类层次结构复杂、代码复用性差等问题。
缺点:

1、多层装饰会增加复杂度:当装饰器层数过多时,会导致代码结构变得复杂,调试和理解起来更加困难。例如,一个对象被多个装饰器层层包裹,追踪方法调用的顺序和逻辑会变得繁琐。

2、性能开销:每个装饰器都需要创建一个对象来包装被装饰对象,这在一定程度上会增加系统的内存开销和方法调用的时间开销。


使用场景: 

(一)需要动态添加功能

        当系统需要在运行时为对象动态添加、移除或替换功能,而不是在编译时通过继承来实现功能扩展时,装饰设计模式是一个很好的选择。比如在图形绘制系统中,为图形动态添加边框、阴影等效果。

(二)避免子类过多

        如果使用继承方式来实现功能扩展,会导致子类数量急剧增加,使得代码难以维护。装饰设计模式通过组合装饰器的方式,将功能扩展逻辑分散到多个装饰器类中,避免了类的爆炸式增长。

(三)对同一对象进行多种组合功能增强

        当需要对同一个对象进行多种不同的功能增强,并且这些功能可以以不同的组合方式应用时,装饰设计模式可以灵活地实现这一需求。例如在游戏角色系统中,为角色添加多种不同的技能组合。

        装饰设计模式通过巧妙的组合方式,实现了对象功能的动态扩展,为软件开发中功能增强的需求提供了一种优雅且灵活的解决方案。它在避免子类泛滥、遵循开闭原则方面表现出色,适用于多种需要动态添加功能的场景。但在使用时,也要注意控制装饰器的层数,避免过度使用导致代码复杂度上升和性能下降。掌握装饰设计模式,能够让我们在面对功能扩展需求时,编写出更加简洁、灵活和可维护的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值