结构性设计模式之装饰器模式

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 结构性设计模式之装饰器模式,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

装饰器模式

概述

装饰器模式(Decorator Pattern)也称为包装模式(Wrapper Pattern),属于结构型模式。

它是指在不改变原有对象的基础之上,允许向一个现有的对象添加新的功能,同时又不改变其结构,作为现有的类的一个包装。

这种模式创建一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

提供了比继承更有单性的替代方案,进行扩展原有对象的功能。

装饰器模式的核心是功能扩展。使用装饰器模式可以透明且动态地扩展类的功能。

装饰器模式主要用于诱明且动态地扩展类的功能。

实现原理

让装饰器实现被包装类相同的接口,使得装饰器与被扩展类类型一致,并在构造函数中传入该接口对象,然后就可以在接口需要实现的方法中在被包装类对象的现有功能上添加新功能。

由于装饰器与被包装类属于同一类型,且构造函数的参数为其实现接口类,因此装饰器模式具备嵌套扩展功能,因此就能使用装饰器模式一层层的对最底层被包装类进行功能扩展。

在JDK中,IO相关包下大量使用装饰器模式,如BufferedReader、InputStream、OutputStream等类

主要角色

装饰器模式主要包含4种角色

1.抽象组件(Component)

抽象组件可以是一个接口或者抽象类,其充当被装饰类的原始对象,规定了被装饰对象的行为。

2.具体组件(ConcreteComponent)

具体组件实现/继承抽象组件的一个具体对象,即被装饰对象。

3.抽象装饰器(Decorator)

通用的装饰具体组件的装饰器,其内部必然有一个属性指向抽象组件;其实现一般是一个抽象类,主要是为了让其子类按照其构造形式传入一个抽象组件,这是强制的通用行为。

如果系统中装饰逻辑单一,并不需要实现许多装饰器,那么可以直接省略该类,而直接实现一个具体装饰器即可。

4.具体装饰器(ConcreteDecorator)

抽象装饰器的具体实现类,理论上,每个具体组件都扩展了抽象组件对象的一种功能。

应用场景

1.用于扩展一个类的功能或给一个类添加附加职责。

2.动态的给一个对象添加功能,这些功能可以再动态的澈销。

3.需要为一批的兄弟类进行改装或加装功能。

优缺点

优点:

1.装饰器是继承的补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用。

2.装饰器完全遵守开闭原则。

缺点:

1.会出现更多的代码,更多的类,增加程序复杂性。

2.通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果。

3.动态装饰时,多层装饰时会更复杂。

装饰器模式的基本使用

创建抽象组件

创建Phone抽象类

public abstract class Phone {
    public abstract String call();
    public abstract double price();
}

具体组件

创建最基本具有打电话功能的手机

public class BasePhone extends Phone {
    @Override
    public String call() {
     return "BasePhone call";
    }

    @Override
    public double price() {
        return 0.1;
    }
}

抽象装饰器

创建一个抽象装饰器来扩展该只具备基本功能的手机

public abstract class PhoneDecorator extends Phone {
    private Phone phone;

    public PhoneDecorator(Phone phone) {
        this.phone = phone;
    }

    @Override
    public String call() {
        return phone.call();
    }

    @Override
    public double price() {
        return phone.price();
    }

    /**
     * 扩展功能
     */
    public abstract void sendMsg();
}

具体装饰器

public class SatellitePhoneDecorator extends PhoneDecorator{
    public SatellitePhoneDecorator(Phone phone) {
        super(phone);
    }

    public void sendMsg() {
        System.out.println("PhoneCallDecorator sendMsg");
    }

    @Override
    public String call() {
        return  "SatellitePhone call";
    }

    @Override
    public double price() {
        return super.price()+100;
    }
}

客户端调用

    public static void main(String[] args) {
        // 创建需要被装饰的原始对象(即要被装饰的对象)
        Phone phone = new BasePhone();
        System.out.println("使用: "+phone.call()+" 方式打电话,每分钟单价:" + phone.price());

        // 给对象透明的增加额外功能并调用
        PhoneDecorator phoneDecorator = new SatellitePhoneDecorator(phone);
        System.out.println("使用: "+phoneDecorator.call()+" 方式打电话,每分钟单价:" + phoneDecorator.price());

        // 装饰器也可以装饰具体的装饰对象,相当于给对象在增加的功能基础上在添加功能,这里体现在单价100.1基础上再+100
        PhoneDecorator satellitePhoneDecorator = new SatellitePhoneDecorator(phoneDecorator);
        System.out.println("使用: "+satellitePhoneDecorator.call()+" 方式打电话,每分钟单价:" + satellitePhoneDecorator.price());
        satellitePhoneDecorator.sendMsg();
    }
使用: BasePhone call 方式打电话,每分钟单价:0.1
使用: SatellitePhone call 方式打电话,每分钟单价:100.1
使用: SatellitePhone call 方式打电话,每分钟单价:200.1
PhoneCallDecorator sendMsg

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136908.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!