装饰器模式

一、装饰器模式

装饰器模式(Decorator Pattern)别名为包装器(Wrapper),是一种对象结构型模式。
定义指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,就扩展功能而言它比生成子类的方式更为灵活
使用频率:3星
模式结构
装饰器模式主要包含以下角色:
1、抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
2、具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
3、抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
4、具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
装饰器模式结构图
在这里插入图片描述
优点
1、装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
2、通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
3、装饰器模式完全遵守开闭原则
缺点
1、装饰器模式会增加许多子类,过度使用会增加程序得复杂性。
应用场景
1、当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。
2、当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰器模式却很好实现。
3、当对象的功能要求可以动态地添加,也可以再动态地撤销时。
额外补充以下知识点涉及应用较少可选择性阅读
装饰模式可分为透明装饰模式和半透明装饰模式两种:
1、在透明(Transparent)装饰模式中,要求客户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该声明具体构件类型和具体装饰类型,而应该全部声明为抽象构件类型。由于客户端是针对抽象构件编程,因此在具体装饰类中新增的方法客户端无法直接调用,这些方法对于客户端而言是不可见的。
2、在半透明(Semi-transparent)装饰模式中,允许用户在客户端声明具体装饰者类型的对象,调用在具体装饰者中新增的方法。对于具体构件使用抽象构件类型声明,但是对于具体装饰者使用具体装饰者类型声明,客户端可以透明对待具体构件但无法透明地对待装饰者,无法实现多次装饰。

二、装饰器模式实例之界面显示构件库

1.实例说明

某软件公司基于面向对象技术开发了一套图形界面显示构件库VisualComponent。在使用该库构建某图形界面时,用户要求界面定制一些特效显示效果,如带滚动条的窗体或透明窗体等。现使用装饰器模式设计该构件库,绘制类图并编程模拟实现。

2.实例类图

在这里插入图片描述

3.实例代码

本例中Window充当抽象构件类,其子类SimpleWindow充当具体构件类,Window类的另一个子类WindowDecorator充当抽象装饰类,WindowDecorator的子类ScrollbarDecorator和TransparentDecorator充当具体装饰者类。

//抽象窗体类:抽象构件类
abstract class Window{
    public abstract void display();
}

//简单窗体类:具体构件类
class SimpleWindow extends Window{
    @Override
    public void display() {
        System.out.println("显示窗体!");
    }
}

//窗体装饰类:抽象装饰者类
class WindowDecorator extends Window{
    private Window window;
    public WindowDecorator(Window window){
        this.window = window;
    }

    @Override
    public void display() {
        window.display();
    }
}

//滚动条窗体装饰类:具体装饰者类
class ScrollbarDecorator extends WindowDecorator{
    public ScrollbarDecorator(Window window){
        super(window);
    }
    public void display(){
        this.setScrollbar();
        super.display();
    }
    public void setScrollbar(){
        System.out.println("给窗体增加滚动条!");
    }
}

//透明窗体装饰类:具体装饰者类
class TransparentDecorator extends WindowDecorator{

    public TransparentDecorator(Window window) {
        super(window);
    }
    public void display(){
        this.setTransparent();
        super.display();
    }
    public void setTransparent(){
        System.out.println("将窗体设置为透明窗体!");
    }
}

客户端测试:

public class Client {
    public static void main(String[] args) {
        Window windowS,windowSB,windowT;
        windowS = new SimpleWindow();
        windowSB = new ScrollbarDecorator(windowS);
        windowT = new TransparentDecorator(windowSB);
        windowT.display();
    }
}

运行结果:

将窗体设置为透明窗体!
给窗体增加滚动条!
显示窗体!

本例使用的是透明装饰模式,抽象类Window的所有子类都实现了display方法,且在具体装饰者类(如ScrollbarDecorator)的display方法中调用新增加的业务方法,对于客户端而言,无论是最简单的窗体类还是装饰过的窗体类都可以使用Window类来进行类型定义,因此对于客户端来说都是透明的。通过引入配置文件,可以很方便地增加或更换具体构件类和具体装饰者类,无须修改源代码,符合开闭原则。在透明装饰模式中,可以对一个对象进行多次装饰,从而使其具有更加强大的功能。

参考文献

【1】装饰器模式(装饰设计模式)详解
【2】设计模式实训教程(第2版) 刘伟 编著 清华大学出版社

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值