装饰者模式

Posted 芬芬是个乖宝宝

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰者模式相关的知识,希望对你有一定的参考价值。

装饰模式介绍

装饰模式是结构型设计模式之一,不使用继承和改变类文件的情况下,动态地扩展一个对象的功能,是继承的替代方案之一(就增加功能来说,装饰者模式相比生成子类更为灵活。)。它是通过创建一个包装对象,也就是装饰来包裹真实的对象,并增加功能。

定义

动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

装饰模式结构图

技术分享

  • Component:被装饰者,给该组件的对象动态的添加功能。
  • ConcreteComponent:组件具体实现类。
  • Decorator:抽象装饰者,继承Component,持有被装饰对象的引用,拓展装饰者的功能。
  • ConcreteDecorator:装饰者具体实现类。

 

 

 

//被装饰者---接口
interface Person {
    void eat();
}

//被装饰者---实现类
class Man implements Person {
    public void eat() {
        System.out.println("男人在吃饭");
    }
}

//装饰者--抽象类,实现了被装饰者接口,持有被装饰者的引用
abstract class Decorator implements Person {

    private Person person;
    
    public Decorator(Person person) {
        this.person = person;
    }
    
    public void eat() {
        person.eat();
    }
}

//定义装饰者A---实现类
class ManDecoratorA extends Decorator {
    public ManDecoratorA(Person person) {
        super(person);
    }
    
    public void eat() {
        super.eat();
        reEat();
        System.out.println("装饰类B");
    }

    public void reEat() {
        System.out.println("再吃一顿炒面");
    }
}

//定义装饰者B---实现类
class ManDecoratorB extends Decorator {
    public ManDecoratorB(Person person) {
        super(person);
    }    
    public void eat() {
        System.out.println("=======例子2========");
        super.eat();
        reEat();
        System.out.println("装饰类A");
    }
    public void reEat() {
        System.out.println("再喝一碗粥");
    }
}

//测试类  
public class Test {  
    public static void main(String[] args) {  
        Man man = new Man();
        ManDecoratorA md1 = new ManDecoratorA(man);
        ManDecoratorB md2 = new ManDecoratorB(man);
   
        md1.eat();
        md2.eat();
    }  
}  

=====================

男人在吃饭
再吃一顿炒面
装饰类B
=======例子2========
男人在吃饭
再喝一碗粥
装饰类A

 

装饰模式的优缺点和使用场景

优点

  • 通过组合而非继承的方式,动态的来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。
  • 有效避免了使用继承的方式扩展对象功能而带来的灵活性差,子类无限制扩张的问题。
  • 具体组件类(被装饰者)与具体装饰类(装饰者)可以独立变化,用户可以根据需要增加新的具体组件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。

缺点

  • 装饰链不能过长,否则会影响效率。
  • 因为所有对象都是继承于Component,所以如果Component内部结构发生改变,则不可避免地影响所有子类(装饰者和被装饰者),如果基类改变,势必影响对象的内部。
  • 比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐,所以只在必要的时候使用装饰者模式。

使用场景

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 需要动态地给一个对象增加功能,这些功能可以动态的撤销。
  • 当不能采用继承的方式对系统进行扩充功能或者采用继承不利于系统扩展和维护时。

 

 

装饰模式和代理模式

代理模式和装饰模式有点像,都是持有了被代理或者被装饰对象的引用。它们两个最大的不同就是装饰模式对引用的对象增加了功能,而代理模式只是对引用对象进行了控制却没有对引用对象本身增加功能

 







以上是关于装饰者模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式之装饰者模式

设计模式整理_装饰者模式

设计模式-装饰者模式(Go语言描述)

设计模式-装饰者模式(Go语言描述)

装饰者模式

设计模式 之 装饰者模式