首页 > 其他分享 >初识设计模式 - 装饰器模式

初识设计模式 - 装饰器模式

时间:2022-09-29 08:45:37浏览次数:58  
标签:器类 void 模式 public 初识 library 设计模式 装饰

简介

装饰器模式主要解决的问题是,如果使用子类继承的方式扩展一个类,随着扩展功能的增多,子类会非常膨胀,包括子类的数量或子类的方法数。

装饰器模式其核心还是“用组合替代继承”,但是相对于普通的组合关系,装饰器模式还有两个比较特殊的地方:

  • 装饰器类和原始类继承同样的父类,这样就可以对原始类“嵌套”多个装饰器类
  • 装饰器类是对功能的加强,这也是装饰器模式应用场景的一个重要特点

具体实现

以图书馆的图书和借阅者为例,在已定义了实体类的基础上,增加借书计数的功能。

定义图书馆的抽象类:

public abstract class Library {
    // 借书
    public abstract void borrowBook();
    // 还书
    public abstract void returnBook();
}

定义具体图书馆类继承抽象图书馆类:

public class ConcreteLibrary extends Library {
    @Override
    public void borrowBook() {
        // 实现类借书
        System.out.println("ConcreteLibrary borrowBook");
    }

    @Override
    public void returnBook() {
        // 实现类还书
        System.out.println("ConcreteLibrary returnBook");
    }
}

定义抽象装饰器类继承抽象图书馆类:

public abstract class LibraryDecorator extends Library {
    protected Library library;

    public LibraryDecorator(Library library) {
        this.library = library;
    }

    @Override
    public void borrowBook() {
        this.library.borrowBook();
    }

    @Override
    public void returnBook() {
        this.library.returnBook();
    }
}

再定义具体的装饰器类继承抽象装饰器类:

public class CountingLibrary extends LibraryDecorator {
    private int counter = 0;

    public CountingLibrary(Library library) {
        super(library);
    }

    @Override
    public void borrowBook() {
        this.library.borrowBook();
        this.counter++;
        this.printCounter();
    }

    @Override
    public void returnBook() {
        this.library.returnBook();
        this.counter--;
        this.printCounter();
    }

    private void printCounter() {
        System.out.println("当前的计数是:" + this.counter);
    }
}

具体分类

在实际使用过程中,为了可以单独调用装饰器类新增的方法,定义这种形式的装饰器模式称为半透明装饰器模式;而标准的装饰器模式是透明装饰器模式。

透明装饰器模式

在透明装饰器模式中,要求客户端完全针对抽象编程,并且可以在具体的装饰器类中将新增行为都定义为私有方法。

如下是推荐的代码示例:

// 使用抽象类型定义对象
Component component = new ConcreteComponent();

如下是不推荐的代码示例:

// 使用具体类型定义对象
ConcreteComponent component = new ConcreteComponent();

透明装饰器模式可以让客户端透明地使用装饰器之前的对象和装饰之后的对象,无需关心它们的区别,使用上没有任何差别。因为,对于我们而言,面向的总是最顶层的抽象类。

半透明装饰器模式

为了能够调用到新增方法,不得不用具体装饰器类型来定义装饰之后的对象,而被装饰的对象还是可以使用抽象类来定义。

其实,也就是因为使用到具体装饰器新增的方法,无法确定这个方法是否在其他同类装饰器上也存在,因此,也就无法嵌套使用装饰器了。

如下是半透明装饰器模式的代码示例:

// 无论是使用具体类型定义对象
ConcreteComponent component = new ConcreteComponent();
// 或者是使用抽象类型定义对象
Component component = new ConcreteComponent();

// 使用具体装饰器类型定义
ConcreteDecorator decorator = new ConcreteDecorator(component);
// 再调用具体装饰器自定义的方法
decorator.otherMethod();

半透明装饰器模式更加灵活,设计相对简单,使用起来也很方便。

但是其最大的缺点是不能实现对同一个对象的多次装饰,而且客户端需要有区别地地对待装饰之前的对象和装饰之后的对象。

总结

优点

装饰器模式的主要优点如下:

  • 对于扩展一个对象的功能,装饰器模式比继承更加灵活,不会导致类的个数急剧增加
  • 可以通过一种动态的方式来扩展一个对象的功能
  • 可以对一个对象进行多次装饰
  • 具体类和具体装饰器类可以独立变化,用户可以根据需要增加新的具体类和具体装饰器类,符合开闭原则

缺点

装饰器模式的主要缺点如下:

  • 使用装饰器模式进行系统设计时将产生很多小对象,如 Java 的 IO 类库
  • 装饰器模式比继承更加灵活,但是也比继承更加容易出错,排错也很困难

适用场景

装饰器模式的适用场景如下:

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
  • 类已经被定义为不可被继承,但是又需要对类进行扩展的情况
  • 系统中存在大量独立的扩展,为支持每一种扩展或者扩展之间的组合将产生大量的子类,使得子类数目呈爆炸性增长

源码

在 JDK 中,提供的 IO 类库使用了装饰器模式。

标签:器类,void,模式,public,初识,library,设计模式,装饰
From: https://www.cnblogs.com/fatedeity/p/16740188.html

相关文章

  • 如何将有参数装饰器的括号去掉,当成无参数装饰器使用
    importtimedefdelayed_start(func=None,*,duration=1):#这一层主要是装饰器参数defdecorator(_func):#这一层主要是将被装饰器装饰的函数传递进来......
  • Python基础(八) | 深浅拷贝、生成器、迭代器以及装饰器详解
    ⭐本专栏旨在对Python的基础语法进行详解,精炼地总结语法中的重点,详解难点,面向零基础及入门的学习者,通过专栏的学习可以熟练掌握python编程,同时为后续的数据分析,机器学习及深......
  • 大话设计模式--------第二章策略模式
    第二章策略模式策略模式的概念很好理解,它将对象和行为分开,将行为定义为一个行为接口和具体行为的实现,每个if判断都可以理解为一个策略。比如商场有三种客户,第一种打8折,......
  • 初识HTML
    HTML简介1.什么是HTML​ HTML的全称为[超文本标记语言,是一种标记语言。它包括一系列标签.通过这些标签可以将网络上的文档格式统一,使分散的Internet资源连接为一个逻辑整......
  • 行为型设计模式之中介者模式
    中介者模式中介者模式又称为调解者模式或调停者模式,属于行为型模式。它用一个中介对象封装系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独......
  • python-装饰器
    装饰器(1)什么是装饰器:器指的是工具,可以定义成函数装饰指的是为其他事务添加额外的东西来点缀上面两者合到一起:装饰器指的是定义一个函数,该函数用来为其他函数添......
  • 行为型设计模式之备忘录模式
    备忘录模式备忘录模式又称为快照模式或令牌模式,属于行为型模式。它是指在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可将该对象......
  • 设计模式 -- Singleton(单例模式)
    单例模式(Singleton)保证一个类仅有一个实例,并提供一个该实例的全局访问点。在软件系统中,经常有这样一个特殊的类,必须保证它们在系统中只存在一个示例,才能确保他们的逻辑......
  • 装饰器基础二装饰类的装饰器
    类可以做装饰器,也可以被装饰器装饰,被装饰器装饰,那这个装饰器可以接收一个类,返回一个类1、装饰类的装饰器-输入类返回类defadd_str(cls):def__str__(self):......
  • 设计模式 -- Flyweight(享元模式)
    享元模式(Flyweight)运用共享技术有效地支持大量的细粒度对象在软件系统采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行是代价——主......