java设计模式-装饰器模式

装饰器模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

设计原则: 对扩展开放,对修改关闭(开闭原则)

装饰者模式-动态地将责任附加到对象上。想要扩展功能,装饰者提供有别于继承的另一种选择

设计背景

手机卡有很多附加业务,比如说彩铃业务、来电显示、加量流量包10G、加量流量包20G、加量通话分钟300分钟等等,都是对手机卡这个具体的对象进行一个功能的附加。比如说A手机卡只需要彩铃业务+来电显示,A手机卡使用了一段时间之后流量不太够用了,想要附加一下加量流量包20G。我们可以使用装饰器模式来很好的实现这个功能。

在这里插入图片描述

模式结构和定义

在这里插入图片描述

  • 抽象构件 (Component):给出抽象接口或抽象类,以规范准备接收附加功能的对象。对应抽象的“手机卡”
  • 具体构件 (ConcreteComponent):定义将要接收附加功能的类。对应具体的"移动手机卡"
  • 抽象装饰 (Decorator):装饰者共同要实现的接口,也可以是抽象类。对应抽象的"各种手机卡附加业务"
  • 具体装饰 (ConcreteDecorator):持有一个 Component 对象,负责给构件对象“贴上”附加的功能。对应具体的 “来电显示”,“加量流量包10G” 等等

java.io 为例

在这里插入图片描述

  • 抽象组件(InputStream) :装饰者模式中的超类,它只有一个抽象方法read(),子类都需要对该方法进行处理被装饰者(FileInputStream , ByteArrayInputStream , StringBufferInputStream) :拥有通用实现read()基本方法

  • 装饰者组件(FilterInputStream) :定义具体装饰者的行为规范,可以做统一基础处理。

  • 具体装饰(BufferedInputStream , DataInputStream , Base64InputStream) :具体的装饰类,拥有对流的读操作做完成具体拓展能力。

应用实例

/**
* 抽象构建 手机卡
*
* @author shengyong.huang
* @date 2020-06-15
*/
public interface SimCard {
    /**
     * 增加手机卡附加业务
     */
    void addAdditionalBusiness();
}
/**
* 具体构建类 中国移动手机卡
*
* @author shengyong.huang
* @date 2020-06-15
*/
public class ChinaMobileSimCard implements SimCard {
    @Override
    public void addAdditionalBusiness() {
        System.out.println("中国移动手机卡A套餐业务");
    }
}
/**
* 抽象装饰手机卡业务
*
* @author shengyong.huang
* @date 2020-06-15
*/
public abstract class SimBusinessDecorator implements SimCard {
    /**
     * 以组合的方式来获取具体构建类
     */
    private SimCard simCard;
    /**
     * 构造方法示例化具体构建对象
     *
     * @param simCard 抽象构建
     */
    public SimBusinessDecorator(SimCard simCard) {
        this.simCard = simCard;
    }
    /**
     * 默认不增加任何行为
     */
    @Override
    public void addAdditionalBusiness() {
        simCard.addAdditionalBusiness();
    }
}
/**
* 彩铃业务装饰器
*
* @author shengyong.huang
* @date 2020-06-15
*/
public class MusicBusinessDecorator extends SimBusinessDecorator {
    public MusicBusinessDecorator(SimCard simCard) {
        super(simCard);
    }
    /**
     * 彩铃业务
     */
    private void music() {
        System.out.println("增加彩铃业务");
    }
    @Override
    public void addAdditionalBusiness() {
        super.addAdditionalBusiness();
        // 对手机卡进行装饰,增加彩铃业务的额外行为
        music();
    }
}
/**
* 来电显示装饰器
*
* @author shengyong.huang
* @date 2020-06-15
*/
public class CallerIdBusinessDecorator extends SimBusinessDecorator {
    public CallerIdBusinessDecorator(SimCard simCard) {
        super(simCard);
    }
    private void callerId() {
        System.out.println("增加来电显示功能");
    }
    @Override
    public void addAdditionalBusiness() {
        super.addAdditionalBusiness();
        // 对手机卡进行装饰,增加来电显示功能的额外行为
        callerId();
    }
}
/**
* 加量10G流量包业务装饰器
*
* @author shengyong.huang
* @date 2020-06-15
*/
public class Add10GFlowPacketBusinessDecorator extends SimBusinessDecorator {
    public Add10GFlowPacketBusinessDecorator(SimCard simCard) {
        super(simCard);
    }
    /**
     * 增加10G流量包
     */
    private void add10G() {
        System.out.println("增加10G流量包");
    }
    @Override
    public void addAdditionalBusiness() {
        super.addAdditionalBusiness();
        // 在原有的基础上增加10G流量包这个额外的行为
        add10G();
    }
}
/**
* @author shengyong.huang
* @date 2020-06-15
*/
public class TestMain {
    public static void main(String[] args) {
        SimCard chinaMobileSimCard = new ChinaMobileSimCard();
        chinaMobileSimCard.addAdditionalBusiness();
        // 装饰彩铃功能
        chinaMobileSimCard = new MusicBusinessDecorator(chinaMobileSimCard);
        chinaMobileSimCard.addAdditionalBusiness();
        // 装饰来电显示
        chinaMobileSimCard = new CallerIdBusinessDecorator(chinaMobileSimCard);
        chinaMobileSimCard.addAdditionalBusiness();
        // 装饰加量流量包
        chinaMobileSimCard = new Add10GFlowPacketBusinessDecorator(chinaMobileSimCard);
        chinaMobileSimCard.addAdditionalBusiness();
    }
}

优点和不足

优点

  • 对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧增加。
  • 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为。
  • 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,得到功能更为强大的对象。
  • 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,原有类库代码无须改变,符合 “开闭原则”。

缺点
使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,大量小对象的产生势必会占用更多的系统资源,在一定程序上影响程序的性能。装饰模式提供了一种比继承更加灵活机动的解决方案,但同时也意味着比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐。

使用场景

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式。不能采用继承的情况主要有两类:
  • 第一类是系统中存在大量独立的扩展,为支持每一种扩展或者扩展之间的组合将产生大量的子类,使得子类数目呈爆炸性增长;
  • 第二类是因为类已定义为不能被继承(如Java语言中的final类)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值