设计模式 - 责任链模式

一、基本介绍

  • 概念:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关

    系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止

  • 模式类型:结构型

  • 设计原则:开闭原则

二、实现

需求:

  • 父系社会,女人逛街在不同阶段需向不同的男人申请
1、一般实现
Ⅰ、代码
// 女人接口
public interface IWomen {
    // 获取个人情况
    int getType();
    // 获取需要请求的事情,逛街、约会?
    String getRequest();
}
// 具体女人实现
public class Women implements IWomen {

    /**
     * 通过一个int类型的参数来描述妇女的个人状况
     * 1--未出嫁
     * 2--出嫁
     * 3--夫死
     */
    private int type;

    private String request;

    public Women(int type,String request) {
        this.type = type;
        this.request = request;
    }

    @Override
    public int getType() {
        return this.type;
    }

    @Override
    public String getRequest() {
        return this.request;
    }
}

// 处理者接口
public interface IHandler {

    // 一个女性(女儿、妻子或者母亲)要求逛街,你要处理这个请求
    void handlerMessage(IWomen iWomen);
}

// 未出嫁时父亲处理
public class Father implements IHandler {

    @Override
    public void handlerMessage(IWomen iWomen) {
        System.out.println("女儿的请示" + iWomen.getRequest());
        System.out.println("父亲答应");
    }
}

// 出嫁后丈夫处理
public class Husband implements IHandler {

    @Override
    public void handlerMessage(IWomen iWomen) {
        System.out.println("妻子的请示" + iWomen.getRequest());
        System.out.println("丈夫答应");
    }
}

// 丈夫死后儿子处理
public class Son implements IHandler {

    @Override
    public void handlerMessage(IWomen iWomen) {
        System.out.println("母亲的请示" + iWomen.getRequest());
        System.out.println("儿子答应");
    }
}

// 具体处理场景
public class Client {
    public static void main(String[] args) {
        Random random = new Random();
        List<IWomen> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new Women(random.nextInt(4), "我要出去逛街"));
        }
        IHandler father = new Father();
        IHandler husband = new Husband();
        IHandler son = new Son();
        for (IWomen iWomen : list) {
            if (iWomen.getType() == 1) {
                father.handlerMessage(iWomen);
            } else if (iWomen.getType() == 2) {
                husband.handlerMessage(iWomen);
            } else if (iWomen.getType() == 3) {
                son.handlerMessage(iWomen);
            } else {

            }
        }
    }
}
Ⅱ、优点
Ⅲ、缺点
  • 职责界定不清晰:原本应该是父亲这个类做的事情抛给了Client类中进行组装进行处理
  • 代码臃肿:随着能处理该类型的请示人员越多,if…else的判断就越多
  • 耦合过重:要根据Women的type来决定使用IHandler的那个实现类来处理请求,IHandler类的实现扩展就需要更改Client,不符合开闭原则
2、模式
  • Women类及接口不变
    在这里插入图片描述
Ⅰ、代码
抽象处理者
public abstract class AbsHandler {
    // 声明所有处理者的处理级别
    protected static final int FATHER_LEVEL_REQUEST = 1;
    protected static final int HUSBAND_level_REQUEST = 2;
    protected static final int SON_LEVEL_REQUEST = 3;
    
    private int level;
    private AbsHandler nextHandler;

    // 具体实现强制初始化级别
    public AbsHandler(int level) {
        this.level = level;
    }

    // 设置下一个处理链
    public void setNextHandler(AbsHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    // 具体处理者的具体处理逻辑
    protected abstract void response(IWomen iWomen);

    // 处理链从头到尾遍历,该自己处理则需要处理,处理不了就传递给下一个处理者
    public final void handlerMessage(IWomen iWomen) {
        if (iWomen.getType() == this.level) {
            this.response(iWomen);
        } else {
            if (this.nextHandler != null) {
                this.nextHandler.handlerMessage(iWomen);
            } else {
                System.out.println("没有可处理的链了");
            }
        }
    }
}
具体处理者
// 具体处理者1
public class Father extends AbsHandler {

    public Father() {
        super(AbsHandler.FATHER_LEVEL_REQUEST);
    }

    @Override
    protected void response(IWomen iWomen) {
        System.out.println("--------女儿向父亲请示-------");
        System.out.println(iWomen.getRequest());
        System.out.println("父亲的答复是:同意\n");
    }
}
// 具体处理者2
public class Husband extends AbsHandler {

    public Husband() {
        super(AbsHandler.HUSBAND_level_REQUEST);
    }

    @Override
    protected void response(IWomen iWomen) {
        System.out.println("--------妻子向丈夫请示-------");
        System.out.println(iWomen.getRequest());
        System.out.println("丈夫的答复是:同意\n");
    }
}

// 具体处理者3
public class Son extends AbsHandler {

    public Son() {
        super(AbsHandler.SON_LEVEL_REQUEST);
    }

    @Override
    protected void response(IWomen iWomen) {
        System.out.println("--------母亲向儿子请示-------");
        System.out.println(iWomen.getRequest());
        System.out.println("儿子的答复是:同意\n");
    }
}
场景类
public class Client {
    public static void main(String[] args) {
        Random random = new Random();
        List<IWomen> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new Women(random.nextInt(4), "我要出去逛街"));
        }
        
        // 也可以将所有的处理者及编排顺序再次进行封装,只返回第一个处理者
        AbsHandler father = new Father();
        AbsHandler husband = new Husband();
        AbsHandler son = new Son();

        father.setNextHandler(husband);
        husband.setNextHandler(son);
        for (IWomen iWomen : list) {
            father.handlerMessage(iWomen);
        }
    }
}
Ⅱ、优点
  • 将请求和处理分开。请求者可以不用知道是谁处理的,处理者可以不用知道请求的全貌,两者解耦,提高系统的灵活性
Ⅲ、缺点
  • 性能问题:每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题。
  • 调试不很方便,特别是链条比较长,环节比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂
Ⅳ、注意事项
  • 链中节点数量需要控制,避免出现超长链的情况,一般的做法是在Handler中设置一个最大节点数量,在setNext方法中判断是否已经超过其阈值,超过则不允许该链建立,避免无意识地破坏系统性能

三、使用场景

1、常见应用场景
Ⅰ、
Ⅱ、
Ⅲ、
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值