23种设计模式之装饰模式

发布于:2024-12-06 ⋅ 阅读:(102) ⋅ 点赞:(0)

1. 简介

装饰模式是一种结构型设计模式,它允许在运行时动态地给一个对象添加新的功能,同时又不改变其结构。这种模式通过创建一个装饰类,将原始对象包装起来,在装饰类中可以添加新的行为或者修改原始对象的行为。
装饰模式就像是给一个基础对象不断地 “穿上” 不同的功能 “外衣”,每一层 “外衣”(装饰类)都可以为对象添加一些额外的特性,而且这些 “外衣” 可以灵活地组合和叠加。

结构和角色

  • 抽象组件(Component):它是定义了被装饰对象的基本接口,既可以是一个抽象类,也可以是一个接口。这个接口声明了被装饰对象和装饰对象共有的方法,客户端代码可以通过这个接口来操作原始对象和装饰后的对象。
  • 具体组件(Concrete Component):它是抽象组件的具体实现类,实现了抽象组件中定义的接口,代表了被装饰的原始对象,提供了基本的功能。
  • 抽象装饰者(Abstract Decorator):它也实现了抽象组件接口,并且通常包含一个对抽象组件的引用。它的主要作用是为具体装饰者提供一个统一的接口,并且可以定义一些公共的装饰方法或者属性。
  • 具体装饰者(Concrete Decorator):它是抽象装饰者的具体实现类,用于给具体组件添加具体的功能。具体装饰者在实现抽象组件接口的方法时,会先调用所引用的抽象组件(原始对象)的方法,然后再添加自己的额外功能。

工作流程

  • 首先创建一个具体组件对象,这个对象提供了基本的功能。
  • 然后根据需要创建一个或多个具体装饰者对象,将具体组件对象传递给具体装饰者对象的构造函数,使得具体装饰者对象可以引用具体组件对象。
  • 当客户端调用具体装饰者对象的方法时,具体装饰者对象会先调用它所引用的具体组件对象的方法,然后再执行自己添加的额外功能。
  • 如果有多个具体装饰者对象,可以将一个具体装饰者对象包装在另一个具体装饰者对象中,形成多层装饰的效果,每次调用方法时,都会依次执行各层装饰者添加的功能和原始对象的功能。

2. 代码

2.1 ABatterCake (抽象组件)

public abstract class ABatterCake {

    protected abstract String getInfo();

    // 价格
    protected abstract int cost();
}

2.2 BatterCake (具体组件)

public class BatterCake extends ABatterCake{
    @Override
    protected int cost() {
        return 5;
    }

    @Override
    protected String getInfo() {
        return "煎饼";
    }
}

2.3 ADecorator (抽象装饰者)

public abstract class ADecorator extends ABatterCake{
    private ABatterCake aBatterCake;

    public ADecorator(ABatterCake aBatterCake) {
        this.aBatterCake = aBatterCake;
    }

    @Override
    protected String getInfo() {
        return this.aBatterCake.getInfo();
    }

    @Override
    protected int cost() {
        return this.aBatterCake.cost();
    }

    // 进行扩展
    protected abstract void doSomething();
}

2.4 EggDecorator (具体装饰者)

public class EggDecorator extends ADecorator{
    public EggDecorator(ABatterCake aBatterCake) {
        super(aBatterCake);
    }

    @Override
    protected void doSomething() {

    }

    @Override
    protected int cost() {
        return super.cost() + 2;
    }

    @Override
    protected String getInfo() {
        return super.getInfo() + " 加一个鸡蛋";
    }
}

2.5 SausageDecorator(具体装饰者)

public class SausageDecorator extends ADecorator{
    public SausageDecorator(ABatterCake aBatterCake) {
        super(aBatterCake);
    }

    @Override
    protected void doSomething() {

    }

    @Override
    protected String getInfo() {
        return super.getInfo() + " 加一根香肠";
    }

    @Override
    protected int cost() {
        return super.cost() + 2;
    }
}

2.6 Test (测试)


public class Test {
    public static void main(String[] args) {
        ABatterCake aBatterCake;
        aBatterCake = new BatterCake();
        aBatterCake = new EggDecorator(aBatterCake);
        aBatterCake = new SausageDecorator(aBatterCake);
        System.out.println("细节:" + aBatterCake.getInfo() + "\n价格: " + aBatterCake.cost());
    }
}

2.7 运行结果

细节:煎饼 加一个鸡蛋 加一根香肠
价格: 9

3. 优缺点

  • 优点
    • 灵活性高:可以在运行时动态地添加或删除对象的功能,通过组合不同的装饰者,可以创造出多种功能组合的对象,满足不同的需求。
    • 符合开闭原则:不需要修改原始类的代码就可以为其添加新的功能。当需要添加新的功能时,只需要创建新的装饰者类并实现相应的装饰逻辑即可。
    • 可维护性好:每个装饰者类只关注自己添加的功能,功能单一,代码结构清晰,便于理解和维护。
  • 缺点
    • 会增加系统的复杂性:随着装饰者的增多,系统中类的数量会增加,尤其是在多层装饰的情况下,代码的逻辑可能会变得复杂,理解和调试成本会增加。
    • 可能会导致设计过度灵活:过度使用装饰模式可能会使系统的设计变得过于复杂和难以控制,在一些简单的场景下可能会显得有些 “大材小用”。

4. 总结


网站公告

今日签到

点亮在社区的每一天
去签到