设计模式-责任链模式

责任链模式

请求发送者和接收者连接成一条链,一个对象处理完,交给下一位,沿着链传递请求,这就是责任链模式。

角色

  • 抽象处理者(Handler)
    定义了处理请求的方法
  • 具体处理者(ContreteHandler)
    包含下一个抽象处理者作为成员变量,不同的处理者实现不同的处理逻辑,处理完了就交给下一个

案例

数据检查者

在使用前端给后端传入的数据前,都需要做校验,比如数据完整性校验等等。一个一个 if-else 写起来比较麻烦,请使用责任链模式优化代码编写体验。

工具类

Mapx

import java.util.HashMap;

public class Mapx<K, V> extends HashMap<K, V> {

    public static Mapx init(String key, Object value) {
        return new Mapx().set(key,value);
    }

    public Mapx<K, V> set(K key, V value){
        this.put(key, value);
        return this;
    }
}

Setx

import java.util.HashSet;

public class Setx extends HashSet {
    public static Setx init(Object obj){
        return new Setx().set(obj);
    }
    public Setx set(Object obj){
        this.add(obj);
        return this;
    }
}

Res:REST接口返回格式生成器

import java.util.Map;

public class Res {
    public static Map ok(String msg, int symbol, Object data) {
        return Mapx.init("code",200)
            .set("symbol",symbol)
            .set("data",data)
            .set("type","ok");
    }
    public static Map fail(String msg, int symbol, Object data) {
        return Mapx.init("code",400)
            .set("symbol",symbol)
            .set("data",data)
            .set("type","fail");
    }
}

Checker:抽象处理者

import java.util.Map;
import java.util.Set;

public interface Checker {
    public Checker hint(String hint);

    public Checker symbol(int symbol);

    public Checker ignore(Object ign);

    public Map check();

    public Checker next(Checker nextChecker);

}

CompleteChecker:完整性检查者

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class CompleteChecker implements Checker{
    private Object suspicion;
    private String hint;
    private int symbol;
    private Set ign;
    private Checker nextChecker;

    public CompleteChecker(Object suspicion) {
        this.suspicion = suspicion;
    }

    @Override
    public Checker hint(String hint) {
        this.hint = hint;
        return this;
    }

    @Override
    public Checker symbol(int symbol) {
        this.symbol = symbol;
        return this;
    }

    @Override
    public Map check() {
        String result = this.is_complete(suspicion, ign);
        if (result!=null){
            Map data = Mapx.init("field", result);
            return Res.fail(hint, symbol, data);
        }
        if (nextChecker!=null){
            return nextChecker.check();
        }
        return null;
    }

    @Override
    public Checker next(Checker nextChecker) {
        this.nextChecker = nextChecker;
        return nextChecker;
    }

    public CompleteChecker ignore(Object ign){
        Set ignx = (Set) ign;
        this.ign = ignx;
        return this;
    }

    private String is_complete(Object obj, Set<String> ign){
        if(obj==null){
            return "Self";
        }
        if(ign==null){
            ign = new HashSet<>();
        }
        Field[] fields = obj.getClass().getDeclaredFields();
        Boolean rs = true;
        for (Field field : fields) {
            field.setAccessible(true);
            Object fieldValue = null;
            String fieldName = "";
            Type fieldType = null;
            try {
                fieldValue = field.get(obj); //得到属性值
                fieldType = field.getGenericType();//得到属性类型
                fieldName = field.getName(); // 得到属性名
//                System.out.println("属性类型:" + fieldType.getTypeName() + ",属性名:" + fieldName + ",属性值:" + fieldValue);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if(ign.contains(fieldName)){
            // System.out.println(fieldName+" 属性忽略检测");
                continue;
            }

            if (fieldValue == null || fieldValue.equals("")) {  //只要有一个属性值不为null 就返回false 表示对象不为null
//                System.out.println("检测的成员变量中有空值");
//                System.out.println(fieldName + "为空");
//                System.out.println(fieldName + ": " + fieldValue);
                return fieldName;
            }
            // 如果成员是列表
            if (fieldValue instanceof java.util.List) {
                if (((List<?>) fieldValue).size()==0){
                    return fieldName;
                }
            }
        }
        return null;
    }
}

Main

public class Main {
    public static void main(String[] args) {

        User user = new User(
            "小靳", "female", 20,
            new User("父亲","male",50,
                new User("爷爷", "male", 70, null))
        );
        Checker checker = new CompleteChecker(user)
            .ignore(Setx.init("age")).hint("user不完整");
        checker.next(new CompleteChecker(user.father))
            .ignore(Setx.init("age")).hint("father不完整")
                .next(new CompleteChecker(user.father.father))
                    .ignore(Setx.init("age")).hint("grandfather不完整");
        System.out.println("检测结果: " + checker.check());

    }
}

Output:

检测结果: {msg=grandfather不完整, symbol=0, code=400, data={field=father}, type=fail}

当然,我这个案例的代码实现存在漏洞,user.father为null的时候,user.father.father是取不到的。


责任链模式的优缺点

优点

  • 使得一个对象无需知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,且链式结构由客户端创建 => 降低了系统的耦合度
  • 在系统中增加一个新的具体处理者无须修改原有系统源代码,只需要在客户端重新建立链式结构即可 => 符合开闭原则

缺点

  • 由于一个请求没有一个明确地接受者 => 无法保证它一定会被处理
  • 对于较长的职责链 => 系统性能有一定影响且不利于调试
  • 如果建立链不当,可能会造成循环调用 => 导致系统进入死循环

应用场景

  • 有多个对象处理同一个请求且无需关心请求的处理对象时谁以及它是如何处理的 => 比如各种审批流程
  • 可以动态地指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中处理者之间的先后次序 => 比如各种流程定制

你可能感兴趣的:(设计模式,设计模式,责任链模式,java,笔记)