栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java设计模式之责任链模式练习

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java设计模式之责任链模式练习

Java中设计模式是为了解决问题,不要为了练习而强行在工程中应用,让原本100行代码就能实现的功能,写了1000行代码,对错不说,增加了代码的复杂度。下面一起看看责任链设计模式,进行练习。
责任链模式,一种行为设计模式,允许你将请求沿着处理者链进行发送,收到请求后,每个处理者均可以对请求进行处理,或将其传递给链上的下个处理者。

责任链模式使用的场景非常多,如审批流程,过滤器filter,在这些场景若不使用设计模式,那么当需求有所改变时,就会使得代码臃肿或难以维护。
实例
一个闯关游戏,进入下一关的条件时上一关的分数要高于XX分:

  • 3个关卡;
  • 若第一关得分大于等于80分则进入第二关;
  • 若第二关得分大于等于90分则进入第三关;

1、最初写法

public class FirstPassHandler {

    public int handler(){
        System.out.println("第一关-->FirstPassHandler");
        return 80;
    }

}
public class SecondPassHandler {

    public int handler(){
        System.out.println("第二关-->SecondPassHandler");
        return 90;
    }

}
public class ThirdPassHandler {

    public int handler(){
        System.out.println("第三关-->ThirdPassHandler,这是最后一关啦");
        return 95;
    }

}

测试调用

	public static void main(String[] args) {
        //第一关
        FirstPassHandler firstPassHandler = new FirstPassHandler();
        //第二关
        SecondPassHandler secondPassHandler = new SecondPassHandler();
        //第三关
        ThirdPassHandler thirdPassHandler = new ThirdPassHandler();
        int firstScore = firstPassHandler.handler();
        //第一关的分数大于等于80则进入第二关
        if(firstScore >= 80){
            int secondScore = secondPassHandler.handler();
            //第二关的分数大于等于90则进入第二关
            if(secondScore >= 90){
                thirdPassHandler.handler();
            }
        }
    }

如果这个游戏有100关,那么调用的代码可能是这样子

		if (1关) {
            //
            if (2关) {
                // 
                if (3关) {
                    // 
                    if (4关) {
                        //
                        if (5关) {
                            //
                            ...
                        }
                    }
                }
            }
        }

这样子的代码不仅冗余,并且当跳转关卡时对代码的改动非常大,风险加大。

2、初步改造
通过链表将每一关连接起来,形成责任链的方式,第一关通过后进入第二关,第二个通过后进入第三关,这样调用就不需要多重if判断了。

public class FirstPassHandler {
    
    private SecondPassHandler secondPassHandler;

    public void setSecondPassHandler(SecondPassHandler secondPassHandler) {
        this.secondPassHandler = secondPassHandler;
    }

    
    private int play(){
        return 80;
    }

    public int handler(){
        System.out.println("第一关-->FirstPassHandler");
        if(play() >= 80){
            //分数>=80 并且存在下一关才进入下一关
            if(this.secondPassHandler != null){
                return this.secondPassHandler.handler();
            }
        }
        return 80;
    }
}
public class SecondPassHandler {

    
    private ThirdPassHandler thirdPassHandler;

    public void setThirdPassHandler(ThirdPassHandler thirdPassHandler) {
        this.thirdPassHandler = thirdPassHandler;
    }

    
    private int play(){
        return 90;
    }

    public int handler(){
        System.out.println("第二关-->SecondPassHandler");
        if(play() >= 90){
            //分数>=90 并且存在下一关才进入下一关
            if(this.thirdPassHandler != null){
                return this.thirdPassHandler.handler();
            }
        }
        return 90;
    }
}
public class ThirdPassHandler {

    
    private int play(){
        return 95;
    }

    
    public int handler(){
        System.out.println("第三关-->ThirdPassHandler,这是最后一关啦");
        return play();
    }
}

测试调用

	public static void main(String[] args) {
        //第一关
        FirstPassHandler firstPassHandler = new FirstPassHandler();
        //第二关
        SecondPassHandler secondPassHandler = new SecondPassHandler();
        //第三关
        ThirdPassHandler thirdPassHandler = new ThirdPassHandler();
        //第一关的下一关是第二关
        firstPassHandler.setSecondPassHandler(secondPassHandler);
        //第二关的下一关是第三关
        secondPassHandler.setThirdPassHandler(thirdPassHandler);
        //说明:因为第三关是最后一关,因此没有下一关
        //开始调用第一关 每一个关卡是否进入下一关卡 在每个关卡中判断
        firstPassHandler.handler();
    }

虽然连接起来了,但每个关卡中都有下一关卡的成员变量,形成链很不方便,扩展性不好。

3、责任链改造
每个关卡中都有下一关卡的成员变量,且是不一样的,可以在关卡上抽象出一个父类或接口,然后每个具体的关卡去继承或实现。

  • 抽象处理者角色:定义一个请求处理的接口,包含抽象处理方法和一个后继连接;
  • 具体处理者角色:实现抽象处理者的处理方法,判断是否处理本次请求,若可以则处理,否则将该请求转给后继者;
  • 测试调用角色:创建处理链,并向链头的具体处理者对象提交请求,不必关心处理细节和请求的传递过程;
public abstract class AbstractHandler {

    
    protected AbstractHandler next;

    public void setNext(AbstractHandler next) {
        this.next = next;
    }

    public abstract int handler();
}
public class FirstPassHandler extends AbstractHandler{

    private int play(){
        return 80;
    }

    @Override
    public int handler(){
        System.out.println("第一关-->FirstPassHandler");
        int score = play();
        if(score >= 80){
            //分数>=80 并且存在下一关才进入下一关
            if(this.next != null){
                return this.next.handler();
            }
        }
        return score;
    }
}
public class SecondPassHandler extends AbstractHandler{

    private int play(){
        return 90;
    }

    @Override
    public int handler(){
        System.out.println("第二关-->SecondPassHandler");
        int score = play();
        if(score >= 90){
            //分数>=90 并且存在下一关才进入下一关
            if(this.next != null){
                return this.next.handler();
            }
        }
        return score;
    }
}
public class ThirdPassHandler extends AbstractHandler{

    private int play(){
        return 95;
    }

    @Override
    public int handler(){
        System.out.println("第三关-->ThirdPassHandler");
        int score = play();
        if(score >= 95){
            //分数>=95 并且存在下一关才进入下一关
            if(this.next != null){
                return this.next.handler();
            }
        }
        return score;
    }
}

测试调用

	public static void main(String[] args) {
        //第一关
        FirstPassHandler firstPassHandler = new FirstPassHandler();
        //第二关
        SecondPassHandler secondPassHandler = new SecondPassHandler();
        //第三关
        ThirdPassHandler thirdPassHandler = new ThirdPassHandler();
        // 和上面没有更改的客户端代码相比,只有这里的set方法发生变化,其他都是一样的
        //第一关的下一关是第二关
        firstPassHandler.setNext(secondPassHandler);
        //第二关的下一关是第三关
        secondPassHandler.setNext(thirdPassHandler);
        //说明:因为第三关是最后一关,因此没有下一关
        //从第一个关卡开始
        firstPassHandler.handler();

    }

4、责任链工厂改造
对于上面的请求链,可以把这个关系维护在配置文件或一个枚举类中。
上一个改造中的抽象类和实现类如上,增加业务链的实体、枚举、链工厂等。

public class PassEntity {

    private String name;

    private String conference;

    private Integer handlerId;

    private Integer preHandlerId;

    private Integer nextHandlerId;

    public PassEntity(String name, String conference, Integer handlerId, Integer preHandlerId, Integer nextHandlerId) {
        this.name = name;
        this.conference = conference;
        this.handlerId = handlerId;
        this.preHandlerId = preHandlerId;
        this.nextHandlerId = nextHandlerId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getConference() {
        return conference;
    }

    public void setConference(String conference) {
        this.conference = conference;
    }

    public Integer getHandlerId() {
        return handlerId;
    }

    public void setHandlerId(Integer handlerId) {
        this.handlerId = handlerId;
    }

    public Integer getPreHandlerId() {
        return preHandlerId;
    }

    public void setPreHandlerId(Integer preHandlerId) {
        this.preHandlerId = preHandlerId;
    }

    public Integer getNextHandlerId() {
        return nextHandlerId;
    }

    public void setNextHandlerId(Integer nextHandlerId) {
        this.nextHandlerId = nextHandlerId;
    }
}
public enum PassEnum {

    // 拦截者名称 全限定类名 handlerId preHandlerId nextHandlerId
    FIRST_HANDLER(new PassEntity("first过滤", "com.FirstPassHandler", 1, null, 2)),
    SECOND_HANDLER(new PassEntity("second过滤", "com.SecondPassHandler", 2, 1, 3)),
    THIRD_HANDLER(new PassEntity("third过滤", "com.ThirdPassHandler", 3, 2, null)),
    ;

    PassEntity passEntity;

    public PassEntity getPassEntity() {
        return passEntity;
    }

    PassEnum(PassEntity passEntity) {
        this.passEntity = passEntity;
    }
}
public interface Pass {

    
    PassEntity getPassEntity(Integer handlerId);

    
    PassEntity getFirstPassEntity();
}
public class PassImpl implements Pass {

    
    private static Map passEntityMap = new HashMap<>();

    static {
        PassEnum[] values = PassEnum.values();
        for (PassEnum value : values) {
            PassEntity passEntity = value.getPassEntity();
            passEntityMap.put(passEntity.getHandlerId(), passEntity);
        }
    }

    @Override
    public PassEntity getPassEntity(Integer handlerId) {
        return passEntityMap.get(handlerId);
    }

    @Override
    public PassEntity getFirstPassEntity() {
        for (Map.Entry entry : passEntityMap.entrySet()) {
            PassEntity value = entry.getValue();
            //  没有上一个handler的就是第一个
            if (value.getPreHandlerId() == null) {
                return value;
            }
        }
        return null;
    }
}

工厂,根据枚举类动态形成一条调用链。

public class PassEnumHandlerFactory {

    private static Pass pass = new PassImpl();

    
    public static AbstractPassHandler getFirstPassHandler() {
        PassEntity firstPassEntity = pass.getFirstPassEntity();
        AbstractPassHandler firstAbstractPassHandler = newPassHandler(firstPassEntity);
        if (firstAbstractPassHandler == null) {
            return null;
        }
        PassEntity tempPassEntity = firstPassEntity;
        Integer nextHandlerId = null;
        AbstractPassHandler tempAbstractPassHandler = firstAbstractPassHandler;
        // 迭代遍历所有handler,以及将它们链接起来
        while ((nextHandlerId = tempPassEntity.getNextHandlerId()) != null) {
            PassEntity passEntity = pass.getPassEntity(nextHandlerId);
            AbstractPassHandler abstractPassHandler = newPassHandler(passEntity);
            tempAbstractPassHandler.setNext(abstractPassHandler);
            tempAbstractPassHandler = abstractPassHandler;
            tempPassEntity = passEntity;
        }
        // 返回第一个handler
        return firstAbstractPassHandler;
    }

    
    private static AbstractPassHandler newPassHandler(PassEntity firstPassEntity) {
        // 获取全限定类名
        String className = firstPassEntity.getConference();
        try {
            // 根据全限定类名,加载并初始化该类,即会初始化该类的静态段
            Class clazz = Class.forName(className);
            return (AbstractPassHandler) clazz.newInstance();
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

}

测试调用

	public static void main(String[] args) {
        AbstractPassHandler firstPassHandler = PassEnumHandlerFactory.getFirstPassHandler();
        firstPassHandler.handler();
    }

责任链模式还需深入理解其应用场景,应用于工程中解决实际问题才是关键,努力吧,少年。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1031270.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号