设计模式2 - 装饰器模式 Decorator Pattern

装饰者模式 : 在不改变原有对象的基础上附加功能,动态的给一个对象添加或者撤销功能 (通过调用super的方法控制执行的顺序),相比生成子类更灵活。

1.装饰者模式应用场景

Java IO流,Mybatis的缓存框架,Spring中的Session等等。

2.装饰者模式优缺点

优点:可以不改变原有对象的情况下动态扩展功能,可以使扩展的多个功能按想要的顺序执行,以实现不同效果。

缺点:更多的类,使程序复杂

3.装饰者模式定义

(1)抽象组件:定义一个抽象接口(或者抽象类),来规范准备附加功能的类

(2)具体组件:将要被附加功能的类,实现抽象构件角色接口

(3)抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口

(4)具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。

说完装饰者的特点后,我这边写个案例帮助大家理解装饰器模式在实际项目种如何运用

案例:  在原有的网关功能基础上扩展新功能

需求分析:网关接口原来的功能,主要是解析数据,对部分数据做脱敏处理,随着业务的发展现在需要在原来功能的基础上扩展新的功能,包括接口的限流操作,接口日志的收集

通过装饰器模式的改造类图的变化如下 

 

代码实现部分

1.定义一个抽象类(原来的代码)

package com.brian.decorative.service;

/**
 * @program: architect
 * @author: Brian Huang
 * @create: 2019-05-14 21:08
 **/
public abstract class BaseGateway {

    public abstract void service();
}

2.定义被装饰角色 (原来的代码)

package com.brian.decorative.service.impl;

import com.brian.decorative.service.BaseGateway;
import lombok.extern.slf4j.Slf4j;

/**
 * @program: architect
 * @author: Brian Huang
 * @create: 2019-05-14 21:15
 **/
@Slf4j
public class DesensitizationComponent  extends BaseGateway {

    @Override
    public void service() {
        log.info("1-->>> 网关中获取基本的操作,数据脱敏...");
    }
}

3.定义抽象装饰角色 (扩展的代码)

package com.brian.decorative.service;

/**
 * @program: architect
 * @author: Brian Huang
 * @create: 2019-05-14 21:13
 **/
public abstract class GatewayDecorate extends BaseGateway {

    private BaseGateway baseGateway;

    public GatewayDecorate(BaseGateway baseGateway) {
        this.baseGateway = baseGateway;
    }

    @Override
    public void service() {
        if(baseGateway !=null){
            baseGateway.service();
        }
    }
}

4.定义具体装饰角色(扩展的代码)

package com.brian.decorative.service.impl;

import com.brian.decorative.service.BaseGateway;
import com.brian.decorative.service.GatewayDecorate;
import lombok.extern.slf4j.Slf4j;

/**
 * @program: architect
 * @author: Brian Huang
 * @create: 2019-05-14 21:16
 **/
@Slf4j
public class LimitComponent extends GatewayDecorate {

    public LimitComponent(BaseGateway baseGateway) {
        super(baseGateway);
    }

    @Override
    public void service() {
        super.service();
        log.info("3-->>> 网关中新增API接口的限流..");
    }
}



----------


package com.brian.decorative.service.impl;

import com.brian.decorative.service.BaseGateway;
import com.brian.decorative.service.GatewayDecorate;
import lombok.extern.slf4j.Slf4j;

/**
 * @program: architect
 * @author: Brian Huang
 * @create: 2019-05-14 21:16
 **/
@Slf4j
public class LogComponent  extends GatewayDecorate {

    public LogComponent(BaseGateway baseGateway) {
        super(baseGateway);
    }

    @Override
    public void service() {
        super.service();
        log.info("2-->>> 网关中新增日志收集..");
    }
}

5.使用工厂获取装饰类(扩展的代码)

package com.brian.decorative.factory;

import com.brian.decorative.service.BaseGateway;
import com.brian.decorative.service.impl.DesensitizationComponent;
import com.brian.decorative.service.impl.LimitComponent;
import com.brian.decorative.service.impl.LogComponent;

/**
 * @program: architect
 * @author: Brian Huang
 * @create: 2019-05-14 21:38
 **/
public class FactoryGateway {

    public static BaseGateway getBaseGateway() {
        return new LimitComponent(new LogComponent(new DesensitizationComponent()));
    }


    public static void main(String[] args) {
        FactoryGateway.getBaseGateway().service();
    }
}

测试结果:

责任链与装饰模式区别:
1.责任链模式下,每个被调用者都持有下一个被调用者的引用,客户端只需要发起一次调用即可,整个过程是链式的调用,从前往后执行。
2.装饰者模式下,持有被装饰的对象,并具备被装饰者的行为,对其行为进行补充增强,整个过程是像包裹住的洋葱,从内层一层向外调用。

装饰器与适配器的区别:
其实适配器模式也是一种包装(Wrapper)模式,它们看似都是起到包装一个类或对象的作用,但是它们使用的目的非常不一样:
1、适配器模式的意义是要将一个接口转变成另外一个接口,它的目的是通过改变接口来达到重复使用的目的
2、装饰器模式不要改变被装饰对象的接口,而是恰恰要保持原有的借口哦,但是增强原有接口的功能,或者改变元有对象的处理方法而提升性能

 

 博客参考:https://www.cnblogs.com/xrq730/p/4908940.html

posted @ 2020-07-09 09:18  Brian_Huang  阅读(215)  评论(0编辑  收藏  举报