设计模式-装饰者模式-以奶茶为例

介绍

装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许在不改变对象原有结构的情况下,动态地添加功能和责任。意如起名,就类似本来有一个房子,在不改变房子本身的情况下给房子添加一些装饰品,家具等,来赋予他们新的功能。是一种继承的替代方式。

装饰者模式的主要结构由以下四个部分构成

定义抽象组件(Component):抽象组件是一个接口或者抽象类,定义了被装饰对象和装饰对象共同实现的方法。在Java中,可以使用接口或者抽象类来实现抽象组件。
定义具体组件(ConcreteComponent):具体组件是实现抽象组件接口或抽象类的一个具体对象。具体组件是被装饰的对象。
定义装饰者抽象类(Decorator):装饰者抽象类继承了抽象组件,并持有一个抽象组件的引用。装饰者抽象类中定义了一个构造函数,用于传入被装饰对象,并且在其中调用抽象组件的方法。
定义具体装饰者类(ConcreteDecorator):具体装饰者类继承了装饰者抽象类,并在其中添加新的行为或者功能。具体装饰者类可以通过组合其他具体装饰者类,实现多个装饰者的嵌套。

直接介绍有点难以理解,接下来结合示例来解释整个结构

实例

以奶茶为例,目前我们奶茶店可以制作两种奶茶,分别为杨枝甘露和芋泥啵啵,同时他们都可以增加小料,小料有芋泥,啵啵,椰果。我们可能会在后续增加新的奶茶品种,同时也可能会增加新的小料。一杯奶茶可以增加多个小料,也可以完全不添加小料。这些都是比较实际且合理的需求。
我们以这个例子来展示装饰者模式。

抽象组件

//抽象组件,定义被装饰者和装饰者都需要实现的装饰方法
public abstract interface MilkyTea {

    //添加小料,这里只有一个小料装饰类,如果还需要添加的种类,可以增加额外的装饰类,也就可以增加额外的抽象方法
    public abstract String addCondiments();
}

被装饰者(具体组件)

杨枝甘露

//具体组件,被装饰类,杨枝甘露
@Data
public class Mango implements MilkyTea {

    @Override
    public String addCondiments() {
        return "杨枝甘露";
    }
}

芋泥啵啵

//具体组件,被装饰类,芋泥啵啵奶茶
@Data
public class TaroBobo implements MilkyTea {

    @Override
    public String addCondiments() {
        return "芋泥啵啵奶茶";
    }
}

装饰者组件(装饰者抽象类)

@Data
//装饰者抽象类,里面需要包含被装饰者类对象,以及需要实现装饰方法
public class Condiment implements MilkyTea {
    protected MilkyTea milkyTea;
    public Condiment(MilkyTea milkyTea)
    {
        this.milkyTea=milkyTea;
    }
    @Override
    public String addCondiments() {
        return milkyTea.addCondiments();
    }
}

这里有两种写法,也可以将该部分改成接口,将对应的被装饰者类对象定义转移至具体装饰者实现类

具体装饰者类

芋泥

public class Taro extends Condiment {
    public Taro(MilkyTea milkyTea)
    {
        super(milkyTea);
    }
    @Override
    public String addCondiments() {
        return milkyTea.addCondiments()+"加小料芋泥";
    }
}

啵啵

public class Bobo extends Condiment {
    public Bobo(MilkyTea milkyTea)
    {
        super(milkyTea);
    }
    @Override
    public String addCondiments() {
        return milkyTea.addCondiments()+"加小料啵啵";
    }
}

椰果

public class Coconut extends Condiment {
    public Coconut(MilkyTea milkyTea)
    {
        super(milkyTea);
    }
    @Override
    public String addCondiments() {
        return milkyTea.addCondiments()+"加小料椰果";
    }
}

测试

   @Test
    public void decorator() {
        Mango mango = new Mango();
        System.out.println(mango.addCondiments());
        Bobo bobo = new Bobo(mango);
        String s = bobo.addCondiments();
        System.out.println(s);
        Taro taro = new Taro(bobo);
        String s1 = taro.addCondiments();
        System.out.println(s1);

        TaroBobo taroBobo = new TaroBobo();
        System.out.println(taroBobo.addCondiments());
        Coconut coconut = new Coconut(taroBobo);
        String s2 = coconut.addCondiments();
        System.out.println(s2);
    }

测试结果

杨枝甘露
杨枝甘露加小料啵啵
杨枝甘露加小料啵啵加小料芋泥
芋泥啵啵奶茶
芋泥啵啵奶茶加小料椰果

总结

通过上面例子可以看出,装饰者模式具有以下一些特点

  1. 可以动态的增加被装饰者的装饰品,具有良好的灵活性及可扩展性,可以增加装饰品种类也可以增加被装饰者种类。
  2. 符合开闭原则,允许行为可以被扩展,而不需修改现有的代码。
  3. 一般情况下,装饰者本身可以对用户透明,用户不必知道装饰者的具体实现,只需要知道其接口。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值