简述设计模式(七)——装饰模式

为何使用装饰模式

在软件开发过程中,当对系统扩展功能时,希望复用当前系统中已存在现存组件,并对其进行动态扩展以实现新功能。此时,在不修改现存组件的情况下,同时对这些组件进行复用扩展。

举个例子,手机本身具备照相功能,但画质感人,爱美的人都希望在拍照的同时具有美化效果,因此,扩展出滤镜、瘦脸等功能。针对这个例子,来看看是否采用装饰模式的方式之间的区别:

  1. 不采用装饰模式;
    重复创建类,会导致类爆炸;
    如果希望其它组件(如相机)也具备扩展功能,也需要重新创建类;
    在这里插入图片描述
  2. 采用装饰模式;
    在这里插入图片描述
    现在我们了解了如何复用现存组件进行扩展的方式,对装饰模式应该有一定的了解。

装饰模式

装饰模式:指在不改变现有对象结构的情况下,动态地给该对象添加额外职责的模式。下面是装饰模式的UML类图:
在这里插入图片描述
装饰模式主要包含以下角色:

  1. 抽象构件(Component):抽象接口,定义规范用于接收扩展功能的对象;
  2. 具体构件(ComponentA):实现抽象构件,通过装饰角色添加额外功能;
  3. 抽象装饰角色(Decorator):继承抽象构件,包含具体构件实例;
  4. 具体装饰角色(DecoratorA):继承抽象装饰,为具体构件添加额外功能;

装饰模式中,具体构件对象和装饰对象共同实现同一接口,同时使用组合关系,装饰角色对象包裹具体构件对象,并在保持具体构件对象的类结构不变的前提下,扩展额外的功能。

代码实现

根据上述手机拍照功能的例子,进行代码实现。

  • 抽象构件
public interface Product {
    void photograph();
}
  • 具体构件
public class Phone implements Product {
    @Override
    public void photograph() {
        System.out.println("手机拍照功能");
    }
}
  • 抽象装饰者
public abstract class AbstractFunction implements Product {

    private Product product;

    public AbstractFunction(Product product) {
        this.product = product;
    }

    @Override
    public void photograph() {
        product.photograph();
    }
}
  • 具体装饰者
public class FilterFunction extends AbstractFunction {

    public FilterFunction(Product product) {
        super(product);
    }

    @Override
    public void photograph() {
        super.photograph();
        filter();
    }

    public void filter(){
        System.out.println("滤镜效果");
    }
}

public class ThinFunction extends AbstractFunction {
    public ThinFunction(Product product) {
        super(product);
    }

    @Override
    public void photograph() {
        super.photograph();
        thin();
    }

    public void thin(){
        System.out.println("瘦脸功能");
    }
}
  • 测试类
public class DecoratorTest {

    public static void main(String[] args) {
        Product phone = new Phone();
        FilterFunction filter = new FilterFunction(phone);
        filter.photograph();

        System.out.println("===================");

        ThinFunction thin = new ThinFunction(phone);
        thin.photograph();

        System.out.println("===================");
        //组合多个功能。
        Product phone1 = new Phone();
        phone1 = new FilterFunction(phone1);
        phone1 = new ThinFunction(phone1);
        phone1.photograph();
    }
}

总结

  • 装饰模式扩展对象功能的方式更加灵活;
  • 可以设计不同的具体装饰类,组合多个不同行为的功能;
  • 缺点是:装饰模式会增加很多子类,如果过度使用会使程序变得复杂;
  • 如果只有一个具体构件而没有抽象构件时,可以让抽象装饰继承具体构件
  • 如果只有一个具体装饰时,可以将抽象装饰和具体装饰合并

使用场景

  1. 给现有类添加附加功能,而且不能采用生成子类的方式进行扩展的情况;
  2. 当需要扩展一组功能进行排列组合,而导致产生很多实现类时,使用继承关系很难实现,就可以考虑使用装饰模式;
  3. 当对象的功能要求可以动态添加、撤销的情况;

参考资料

装饰模式(装饰设计模式)详解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值