Java 设计模式 责任链模式详解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/LZHH_2008/article/details/93967841

责任链模式是一种常见的行为模式。

一.责任链模式的现实场景

习伟过生日邀请了很多朋友到KTV一起庆祝,为了增加欢乐的气氛,习伟建议大家一起玩击鼓传花的游戏。由习伟击鼓,大家依次往下传花,鼓声停下来时,花在谁手上就要喝酒并且还要唱一首歌。 
大家都很踊跃地参加这个游戏,聚会的气氛很快热闹起来,习伟也度过了一个很快乐的生日聚会。

在上面的这个场景中,击鼓传花的这个游戏过程类似于设计模式中的责任链模式,就是要事件不断的进行传递,直到事件被执行为止。

二.责任链模式(Chain of Respinsibility Pattern)的定义


使多个对象都有处理请求的机会,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象串成一条链,并沿着这条链依次传递请求,直到有对象处理它为止。

 

四.责任链模式的两个角色
1.抽象处理者(Handler)角色
该角色对请求进行抽象,并定义一个方法来设定和返回对下一个处理者的引用。

2.具体处理者(Concrte Handler)角色
该角色接到请求后,可以选择将请求处理掉,或者将请求传递给下一个处理者。 
由于具体处理者持有对下一个处理者的引用,因此,如果需要,具体处理者可以访问下一个处理者,把问题給下一个处理者,并以此类推。

五.责任链模式的优缺点
责任链模式中的优点
1. 责任链模式将请求和处理分开,请求者不知道是谁处理,处理者可以不用知道请求者全貌。
2. 提高系统的灵活性
命令模式的缺点
1.降低程序的性能。每个请求都是从链头遍历到链尾,当遇到链比较长的时候,性能就会大幅下降。
2.不易于调试,由于该模式采用了类似递归的方式,调试的时候逻辑比较复杂。
责任链中的节点数量需要控制,避免出现超长链的情况,这就需要设置一个最大的节点数量,一旦超过则不允许增加节点,避免责任链无意识地破化系统性能。

六.责任链模式的使用场景
责任链模式是一种常见的模式,Struts2的核心控件FilterDispatcher是一个Servlet过滤器,该控件就是采用责任链模式,可以对用户请求进行层层过滤处理。责任链模式在实际项目中的使用也是有的,其典型的应用场景如下:

1.一个请求需要一系列的处理工作。
2.业务流的处理,例如文件审批。
3.对系统进行扩展。
七.责任链模式的示例
示例代码  击鼓传花, 输者喝酒

抽象处理类Player

package com.chain.test;

public abstract class Player {

    //具体做事的人
    private  Player dirnk;

    public Player getDirnk() {
        return dirnk;
    }

    //传入下一个具体做事的人
    public void setDirnk(Player dirnk) {
        this.dirnk = dirnk;
    }
    
    //传到的过程
    public abstract void handle(int i);
    
    public void next(int index) {
        if(dirnk != null) {
            dirnk.handle(index);
        }else {
            System.out.println("game over!");
        }
    }
}

具体处理类PlayerA

package com.chain.test;

/**
 * 游戏参与者
 * @author pc
 *
 */
public class PlayerA extends Player {
    
    //构造方法  传入下一个 游戏参与者
    public PlayerA(Player drink) {
        this.setDirnk(drink);
    }

    //游戏过程
    @Override
    public void handle(int i) {
        
        if(i%5==1) {
            System.out.println("PlayerA drink!");
        }else {
            System.out.println("PlayerA next!");
            next(i);
        }

    }

}

具体处理类PlayerB

package com.chain.test;

/**
 * 游戏参与者
 * @author pc
 *
 */
public class PlayerB extends Player {

    //构造方法  传入下一个 游戏参与者
    public PlayerB(Player drink) {
        this.setDirnk(drink);
    }
    
    //游戏过程
    @Override
    public void handle(int i) {
        
        if(i%5==2) {
            System.out.println("PlayerB drink!");
        }else {
            System.out.println("PlayerB next!");
            next(i);
        }

    }

}
 

具体处理类PlayerC

package com.chain.test;

public class PlayerC extends Player {

    //构造方法  传入下一个 游戏参与者
    public PlayerC(Player drink) {
        this.setDirnk(drink);
    }
    
    //游戏过程
    @Override
    public void handle(int i) {
        
        if(i%5==3) {
            System.out.println("PlayerC drink!");
        }else {
            System.out.println("PlayerC next!");
            next(i);
        }

    }

}
 

具体处理类PlayerD

package com.chain.test;

public class PlayerD extends Player {

    //构造方法  传入下一个 游戏参与者
    public PlayerD(Player drink) {
        this.setDirnk(drink);
    }
    
    //游戏过程
    @Override
    public void handle(int i) {
        
        if(i%5==4) {
            System.out.println("PlayerD drink!");
        }else {
            System.out.println("PlayerD next!");
            next(i);
        }

    }

}
 

具体处理类PlayerE

package com.chain.test;

public class PlayerE extends Player {

    //构造方法  传入下一个 游戏参与者
    public PlayerE(Player drink) {
        this.setDirnk(drink);
    }
    
    //游戏过程
    @Override
    public void handle(int i) {
        
        if(i%5==0) {
            System.out.println("PlayerE drink!");
        }else {
            System.out.println("PlayerE next!");
            next(i);
        }

    }

}
 

测试类:

package com.chain.test;

/**
 * 测试
 * @author pc
 *
 */
public class TestChain {

     public static void main(String args[]){
            //创建一个链
            PlayerA playerA = null;
            PlayerE playerE=new PlayerE(playerA);
            PlayerD playerD=new PlayerD(playerE);
            PlayerC playerC=new PlayerC(playerD);
            PlayerB playerB=new PlayerB(playerC);
            //PlayerA playerA=new PlayerA(playerB);
            playerA=new PlayerA(playerB);
            //击鼓下停下来
            playerA.handle(5);
        }
}

运行结果:

PlayerA next!
PlayerB next!
PlayerC next!
PlayerD next!
PlayerE drink!

但是实际生活的传花游戏,一般循环 ,这就需要改造每个类的  if(i%N==0)  即可实现

原文:https://blog.csdn.net/wenzhi20102321/article/details/79333899 
 

猜你喜欢

转载自blog.csdn.net/LZHH_2008/article/details/93967841