装饰者模式

    装饰者模式拥有一个设计非常巧妙的结构,它可以动态添加对象功能。在基本的设计原则中,有一条重要的设计准则叫做合成/聚合复用原则。根据该原则的思想,代码复用应该尽可能使用委托,而不是使用继承。因为继承是一种紧耦合,任何父类的改动都会影响其子类,不利于系统维护。而委托则是松散耦合,只要接口不变,委托类的改动不会影响其上层对象。

    装饰者模式充分利用这种思想,通过委托机制,复用系统中的各个组件,在运行时,可以将这些功能进行叠加,从而构造一个超级对象,使其拥有这些组件的功能。而各个子功能模块,被很好的维护在各个组件的相关类中,拥有整洁的系统结构。

    装饰者模式可以有效分离性能组件和功能组件,从而提升模块的可维护性并增加模块的复用性。

    角色:组件接口—-组件接口是装饰者和被装饰者的超类或者接口,定义了被装饰者的核心功能和装饰者需要加强的功能点;具体组件—-具体组件实现了组件接口的核心方法,完成某一个具体的业务逻辑,也是被装饰的对象;装饰者—-实现组件接口,并持有一个具体的被装饰者对象;具体装饰者—-具体实现装饰的业务逻辑,即实现了被分离的各个增强功能点,各个具体装饰者是可以相互叠加的,从而可以构成一个功能更加强大的组件对象。

    装饰者和被装饰者拥有相同的接口,被装饰者通常是系统的核心组件,完成特定的功能目标,而装饰者则可以在被装饰者的方法前后,加上特定的前置处理和后置处理,增强被装饰者的功能。

    装饰者的一个典型案列是对输出结果进行增强。例,现在需要将某一结果通过HTML进行发布,则首先需要将内容转换为Html文本,同时由于内容需要在网络上通过Http流传,所以还需要增加Http头。装饰者模式的核心在于:无需将所有的逻辑,即核心内容构建、HTML文本构造和HTTP头生成等3个功能模块粘合在一起实现。通过装饰者,将他们分解为3个几乎完全独立的组件2,并在使用时灵活的进行装配。

    组件接口:

/**
 * 组件接口 定义了被装饰者的核心功能和装饰者需要增强的功能点
 * @author qiaolin
 *
 */
public interface IPacketCreator {
    String handleContent();//用于内容处理
}

    具体组件–被装饰者:

package com.performance.optimization.design.decorator;

/**
 * 被装饰者(具体组件)  返回数据包的核心数据 也是主要的业务处理
 * @author qiaolin
 *
 */
public class PacketBodyCreator implements IPacketCreator{

    public String handleContent() {
        return "Content of Packet";
    }

}

    装饰者— 抽象类:

package com.performance.optimization.design.decorator;

/**
 * 装饰者  维护核心组件对象,负责告诉其子类,其核心业务逻辑处理全权委托给组件对象完成,自己仅作增强处理
 * @author qiaolin
 *
 */
public abstract class PacketDecorator implements IPacketCreator{

     protected IPacketCreator component;

     public PacketDecorator(IPacketCreator component){
         this.component = component;
     }

}

    具体装饰者:

package com.performance.optimization.design.decorator;

/**
 * 具体的装饰器 负责对核心内容进行html格式化操作,委托了组件进行核心业务处理
 * @author qiaolin
 *
 */
public class PacketHTMLHeaderCreator extends PacketDecorator {

    public PacketHTMLHeaderCreator(IPacketCreator component) {
        super(component);
    }

    /**
     * 封装数据为html
     */
    public String handleContent() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<html>");
        buffer.append("<body>");
        buffer.append(component.handleContent());//业务逻辑处理
        buffer.append("</body>");
        buffer.append("</html>\n");
        return buffer.toString();
    }

}
package com.performance.optimization.design.decorator;

import java.util.Date;

/**
 * 具体的装饰器 负责对数据头加上HTTP头信息
 * @author qiaolin
 *
 */
public class PacketHTTPHeaderCreator extends PacketDecorator{

    public PacketHTTPHeaderCreator(IPacketCreator component) {
        super(component);
    }

    /**
     * 对给定数据加上消息头
     */
    public String handleContent() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("Cache-Control:no-cache\n");
        buffer.append("Date:" + new Date() + "\n");
        buffer.append(component.handleContent());
        return buffer.toString();
    }

}

    装饰者模式测试:

    /**
     * 将装饰者和被装饰者组装在一起
     */
    @Test
    public void test(){
        IPacketCreator component = new PacketHTTPHeaderCreator(
                new PacketHTMLHeaderCreator(new PacketBodyCreator()));
        System.out.println(component.handleContent());
    }

    装饰者模式测试结果:

Cache-Control:no-cache
Date:Mon Aug 08 13:42:01 CST 2016
<html><body>Content of Packet</body></html>

    通过装饰者的构造函数,将被装饰者对象传入。生成的对象实例从最里面开始创建,即作为核心组件最先被创建。在JDK的实现中,有不少组件也是使用装饰者模式实现的,其中一个典型的例子是OutputStream和InputStream类族的实现。其中组件接口是OutputStream这个抽象类,FileOutputStream是装饰者也是被装饰者,具体的装饰者是FileOutputStream的子类,

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值