问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

装饰模式(Decorator Pattern)- 最通俗易懂的案例

创作时间:
作者:
@小白创作中心

装饰模式(Decorator Pattern)- 最通俗易懂的案例

引用
CSDN
1.
https://blog.csdn.net/weixin_39296283/article/details/104970189

装饰模式(Decorator Pattern)是一种结构型设计模式,它允许在运行时动态地给对象添加新的功能。与继承相比,装饰模式更加灵活,可以避免类爆炸的问题。本文将通过一个通俗易懂的案例,详细介绍装饰模式的概念、结构和实现。

前言

在软件开发中,我们常常需要扩展一个类的功能。传统的做法是通过继承来实现,但这种方法存在一些缺点,比如单继承的局限性和可能产生类爆炸的后果。装饰模式(Decorator)提供了一种更灵活的解决方案,它可以在不改变原有类结构的情况下,动态地给对象添加新的功能。

装饰模式属于结构型模式,它的核心思想是将对象包装在装饰器中,通过装饰器来扩展对象的功能。被装饰的对象和装饰器之间不需要相互了解,这使得它们可以独立发展,互不影响。

结构模式图

  • Component:定义一个对象接口,可以给这些对象动态地添加职责。
  • ConcreteComponent:定义了一个具体的对象,也可以给这个对象添加一些职责。
  • Decorator:装饰抽象类,继承了 Component,从外类来扩展Component的功能,但对于Component来说,是无需知道Decorator的存在的。
  • ConcreteDecoratorA/B:具体的装饰对象,起到给Component添加职责的功能。

案例实现

想象一下这个情景:清晨上班的你在路上遇到一家面馆,你便进去点了一碗面吃,然后你又发现菜单栏上有许多的配料:牛肉、荷包蛋、鸡腿,这时你看到旁边的一个老板把这三个全部点了一遍加到他的面里,于是你也不甘示弱,但作为程序员的你只加了一个荷包蛋进去。

现在我们用装饰模式来完成上面这个需求:往面条里面加配料。

定义对象接口

package com.design_pattern.decorator;

public interface INoodles {
    public void cook();
}

具体实现类

package com.design_pattern.decorator;

public class Noodles implements INoodles {
    @Override
    public void cook() {
        System.out.println("的面条");
    }
}

抽象装饰类

package com.design_pattern.decorator;

public abstract class NoodlesDecorator implements INoodles {
    private INoodles noodles;    //添加一个INoodles 的引用
    public NoodlesDecorator(INoodles noodles){     //通过构造器来设置INoodles 
        this.noodles = noodles;
    }
    @Override
    public void cook() {
        if (noodles!=null){
            noodles.cook();
        }
    }
}

具体装饰类

EggDecorator

package com.design_pattern.decorator;

public class EggDecorator extends NoodlesDecorator {
    public EggDecorator(INoodles noodles) {
        super(noodles);
    }
    @Override
    public void cook() {
        System.out.println("加了一个荷包蛋");
        super.cook();
    }
}

BeefDecorator

package com.design_pattern.decorator;

public class BeefDecorator extends NoodlesDecorator {
    public BeefDecorator(INoodles noodles) {
        super(noodles);
    }
    @Override
    public void cook() {
        System.out.println("加了一斤牛肉");
        super.cook();
    }
}

ChickenLegDecorator

package com.design_pattern.decorator;

public class ChickenLegDecorator extends NoodlesDecorator {
    public ChickenLegDecorator(INoodles noodles) {
        super(noodles);
    }
    @Override
    public void cook() {
        System.out.println("加了一个鸡腿");
        super.cook();
    }
}

客户端代码

package com.design_pattern.decorator;

public class Client {
    public static void main(String[] args) {
        //一位老板来了说我全要
        INoodles noodles = new Noodles();
        INoodles noodlesWithEgg = new EggDecorator(noodles);
        INoodles noodlesWithEggAndChickenLeg = new ChickenLegDecorator(noodlesWithEgg);
        INoodles noodlesWithEggAndChickenLegAndBeef = new BeefDecorator(noodlesWithEggAndChickenLeg);
        noodlesWithEggAndChickenLegAndBeef.cook();
        System.out.println("************分割线**************");
        //咱是程序员,咱加一个蛋就行了
        INoodles noodles1 = new Noodles();
        INoodles noodles1WithEgg = new EggDecorator(noodles1);
        noodles1WithEgg.cook();
    }
}

打印输出:

加了一斤牛肉
加了一个鸡腿
加了一个荷包蛋
的面条
************分割线**************
加了一个荷包蛋
的面条

总结

优缺点分析

优点:

  • 装饰类和被装饰类可以独立发展,不会相互耦合。
  • 装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

缺点:

  • 多层装饰比较复杂。

使用场合

  • 如果你希望在无需修改代码的情况下即可使用对象,且希望在运行时为对象新增额外的行为,可以使用装饰模式。
  • 如果用继承来扩展对象行为的方案难以实现或者根本不可行,你可以使用该模式。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号