23种设计模式学习笔记(7)

勤奋不是嘴上说说而已,而是实际的行动,在勤奋的苦度中持之以恒,永不退却。业精于勤,荒于嬉;行成于思,毁于随。在人生的仕途上,我们毫不迟疑地选择勤奋,她是几乎于世界上一切成就的催产婆。只要我们拥着勤奋去思考,拥着勤奋的手去耕耘,用抱勤奋的心去对待工作,浪迹红尘而坚韧不拔,那么,我们的生命就会绽放火花,让人生的时光更加的闪亮而精彩。

导读:本篇文章讲解 23种设计模式学习笔记(7),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

23种设计模式学习笔记(1)
https://blog.csdn.net/qq_51495235/article/details/115358623

23种设计模式学习笔记(2)
https://blog.csdn.net/qq_51495235/article/details/115358846

23种设计模式学习笔记(3)
https://blog.csdn.net/qq_51495235/article/details/115359128

23种设计模式学习笔记(4)
https://blog.csdn.net/qq_51495235/article/details/115359246

23种设计模式学习笔记(5)
https://blog.csdn.net/qq_51495235/article/details/115359272

23种设计模式学习笔记(6)
https://blog.csdn.net/qq_51495235/article/details/115359367

25,状态模式

25.1 状态模式的定义和特点

状态(State)模式的定义:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。

状态模式是一种对象行为型模式,其主要优点如下。

  1. 结构清晰,状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”。
  2. 将状态转换显示化,减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
  3. 状态类职责明确,有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。

状态模式的主要缺点如下。

  1. 状态模式的使用必然会增加系统的类与对象的个数。
  2. 状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。
  3. 状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源码。

25.2 状态模式的结构与实现

【例】通过按钮来控制一个电梯的状态,一个电梯有开门状态,关门状态,停止状态,运行状态。每一种状态改变,都有可能要根据其他状态来更新处理。例如,如果电梯门现在处于运行时状态,就不能进行开门操作,而如果电梯门是停止状态,就可以执行开门操作

23种设计模式学习笔记(7)

public interface ILift {
    //电梯的4个状态
    //开门状态
    public final static int OPENING_STATE = 1;
    //关门状态
    public final static int CLOSING_STATE = 2;
    //运行状态
    public final static int RUNNING_STATE = 3;
    //停止状态
    public final static int STOPPING_STATE = 4;

    //设置电梯的状态
    public void setState(int state);

    //电梯的动作
    public void open();
    public void close();
    public void run();
    public void stop();
}

public class Lift implements ILift {
    private int state;

    @Override
    public void setState(int state) {
        this.state = state;
    }

    //执行关门动作
    @Override
    public void close() {
        switch (this.state) {
            case OPENING_STATE:
                System.out.println("电梯关门了。。。");//只有开门状态可以关闭电梯门,可以对应电梯状态表来看
                this.setState(CLOSING_STATE);//关门之后电梯就是关闭状态了
                break;
            case CLOSING_STATE:
                //do nothing //已经是关门状态,不能关门
                break;
            case RUNNING_STATE:
                //do nothing //运行时电梯门是关着的,不能关门
                break;
            case STOPPING_STATE:
                //do nothing //停止时电梯也是关着的,不能关门
                break;
        }
    }

    //执行开门动作
    @Override
    public void open() {
        switch (this.state) {
            case OPENING_STATE://门已经开了,不能再开门了
                //do nothing
                break;
            case CLOSING_STATE://关门状态,门打开:
                System.out.println("电梯门打开了。。。");
                this.setState(OPENING_STATE);
                break;
            case RUNNING_STATE:
                //do nothing 运行时电梯不能开门
                break;
            case STOPPING_STATE:
                System.out.println("电梯门开了。。。");//电梯停了,可以开门了
                this.setState(OPENING_STATE);
                break;
        }
    }

    //执行运行动作
    @Override
    public void run() {
        switch (this.state) {
            case OPENING_STATE://电梯不能开着门就走
                //do nothing
                break;
            case CLOSING_STATE://门关了,可以运行了
                System.out.println("电梯开始运行了。。。");
                this.setState(RUNNING_STATE);//现在是运行状态
                break;
            case RUNNING_STATE:
                //do nothing 已经是运行状态了
                break;
            case STOPPING_STATE:
                System.out.println("电梯开始运行了。。。");
                this.setState(RUNNING_STATE);
                break;
        }
    }

    //执行停止动作
    @Override
    public void stop() {
        switch (this.state) {
            case OPENING_STATE: //开门的电梯已经是是停止的了(正常情况下)
                //do nothing
                break;
            case CLOSING_STATE://关门时才可以停止
                System.out.println("电梯停止了。。。");
                this.setState(STOPPING_STATE);
                break;
            case RUNNING_STATE://运行时当然可以停止了
                System.out.println("电梯停止了。。。");
                this.setState(STOPPING_STATE);
                break;
            case STOPPING_STATE:
                //do nothing
                break;
        }
    }
}

public class Client {
    public static void main(String[] args) {
        Lift lift = new Lift();
        lift.setState(ILift.STOPPING_STATE);//电梯是停止的
        lift.open();//开门
        lift.close();//关门
        lift.run();//运行
        lift.stop();//停止
    }
}

23种设计模式学习笔记(7)

问题分析

  • 使用了大量的switch…case这样的判断(if…else也是一样),使程序的可阅读性变差。
  • 扩展性很差。如果新加了断电的状态,我们需要修改上面判断逻辑

25.2.1 状态模式的结构

  • 环境(Context)角色:也称为上下文,它定义了客户程序需要的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
  • 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
  • 具体状态(Concrete State)角色:实现抽象状态所对应的行为。

25.2.2 代码实现

关系类图

23种设计模式学习笔记(7)

LiftState

package com.zhuang.state.after;

/**
 * @Classname LiftState
 * @Description 抽象状态类
 * @Date 2021/3/31 10:50
 * @Created by dell
 */

public abstract class LiftState {
    //定义一个环境角色,也就是封装状态的变化引起的功能变化
    protected Context context;

    public void setContext(Context context) {
        this.context = context;
    }

    //电梯开门动作
    public abstract void open();

    //电梯关门动作
    public abstract void close();

    //电梯运行动作
    public abstract void run();

    //电梯停止动作
    public abstract void stop();
}

Context

package com.zhuang.state.after;

/**
 * @Classname Context
 * @Description 定义所有电梯门状态
 * @Date 2021/3/31 10:53
 * @Created by dell
 */

public class Context {
    //定义出所有的电梯状态
    //开门状态,这时候电梯只能关闭
    public final static OpeningState OPENNING_STATE = new OpeningState();
    //关闭状态,这时候电梯可以运行、停止和开门
    public final static ClosingState CLOSEING_STATE = new ClosingState();
    //运行状态,这时候电梯只能停止
    public final static RunningState RUNNING_STATE = new RunningState();
    //停止状态,这时候电梯可以开门、运行
    public final static StoppingState STOPPING_STATE = new StoppingState();


    //定义一个当前电梯状态
    private LiftState liftState;

    public LiftState getLiftState() {
        return this.liftState;
    }

    public void setLiftState(LiftState liftState) {
        //当前环境改变
        this.liftState = liftState;
        //把当前的环境通知到各个实现类中
        this.liftState.setContext(this);
    }

    public void open() {
        this.liftState.open();
    }

    public void close() {
        this.liftState.close();
    }

    public void run() {
        this.liftState.run();
    }

    public void stop() {
        this.liftState.stop();
    }
}

OpeningState

package com.zhuang.state.after;

/**
 * @Classname OpeningState
 * @Description 开启状态
 * @Date 2021/3/31 10:51
 * @Created by dell
 */

public class OpeningState extends LiftState {


    //开启当然可以关闭了,我就想测试一下电梯门开关功能
    @Override
    public void open() {
        System.out.println("电梯门开启...");
    }

    @Override
    public void close() {
        //状态修改
        super.context.setLiftState(Context.CLOSEING_STATE);
        //动作委托为CloseState来执行,也就是委托给了ClosingState子类执行这个动作
        super.context.getLiftState().close();

    }

    //电梯门不能开着就跑,这里什么也不做
    @Override
    public void run() {
        //do nothing
    }

    //开门状态已经是停止的了
    @Override
    public void stop() {
        //do nothing
    }
}

ClosingState

package com.zhuang.state.after;

/**
 * @Classname ClosingState
 * @Description 关闭状态
 * @Date 2021/3/31 10:52
 * @Created by dell
 */

public class ClosingState extends LiftState {
    @Override
    //电梯门关闭,这是关闭状态要实现的动作
    public void close() {
        System.out.println("电梯门关闭...");
    }

    //电梯门关了再打开,逗你玩呢,那这个允许呀
    @Override
    public void open() {
        super.context.setLiftState(Context.OPENNING_STATE);
        super.context.open();
    }


    //电梯门关了就跑,这是再正常不过了
    @Override
    public void run() {
        super.context.setLiftState(Context.RUNNING_STATE);
        super.context.run();
    }

    //电梯门关着,我就不按楼层
    @Override
    public void stop() {
        super.context.setLiftState(Context.STOPPING_STATE);
        super.context.stop();
    }
}

RunningState

package com.zhuang.state.after;

/**
 * @Classname RunningState
 * @Description 运行状态
 * @Date 2021/3/31 10:52
 * @Created by dell
 */

public class RunningState extends LiftState {

    @Override
    public void open() {
        //什么也不做
    }

    @Override
    public void close() {
        //什么也不做
    }

    @Override
    public void run() {
        System.out.println("电梯正在运行...");
    }

    @Override
    public void stop() {
        //停止
        super.context.setLiftState(Context.OPENNING_STATE);
        super.context.stop();
    }
}

StoppingState

package com.zhuang.state.after;

/**
 * @Classname StoppingState
 * @Description 停止状态
 * @Date 2021/3/31 10:51
 * @Created by dell
 */

public class StoppingState extends LiftState {

    @Override
    public void open() {
        //状态修改
        super.context.setLiftState(Context.OPENNING_STATE);
        //动作委托给CloseState来执行 也就是委托给了ClosingState子类执行动作
        super.context.getLiftState().open();
    }

    @Override
    public void close() {
        //状态修改
        super.context.setLiftState(Context.CLOSEING_STATE);
        //动作委托给CloseState来执行 也就是委托给了ClosingState子类执行动作
        super.context.getLiftState().close();
    }

    @Override
    public void run() {
        //状态修改
        super.context.setLiftState(Context.RUNNING_STATE);
        //动作委托给CloseState来执行 也就是委托给了ClosingState子类执行动作
        super.context.getLiftState().run();
    }

    @Override
    public void stop() {
        System.out.println("电梯停止了...");
    }
}

Client

package com.zhuang.state.after;

/**
 * @Classname Client
 * @Description 状态模式 测试类
 * @Date 2021/3/31 10:53
 * @Created by dell
 */

public class Client {
    public static void main(String[] args) {
        //开门状态
        System.out.println("开门状态-->");
        Context context1 = new Context();
        context1.setLiftState(new OpeningState());
        context1.open();
        context1.close();
        context1.run();
        context1.stop();

        System.out.println("=========================");
        //关门状态
        System.out.println("关门状态-->");
        Context context2 = new Context();
        context2.setLiftState(new ClosingState());
        context2.open();
        context2.close();
        context2.run();
        context2.stop();

        System.out.println("=========================");
        //运行状态
        System.out.println("运行状态-->");
        Context context3 = new Context();
        context3.setLiftState(new RunningState());
        context3.open();
        context3.close();
        context3.run();
        context3.stop();

        System.out.println("=========================");
        //停止状态
        System.out.println("停止状态-->");
        Context context4 = new Context();
        context4.setLiftState(new StoppingState());
        context4.open();
        context4.close();
        context4.run();
        context4.stop();


    }
}

23种设计模式学习笔记(7)

25.3 状态模式应用场景

  • 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。
  • 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。

26,策略模式

26.1 策略模式的定义和特点

策略(Strategy)模式的定义:**该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。**策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

策略模式的主要优点如下。

  1. 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if…else 语句、switch…case 语句。
  2. 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
  3. 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
  4. 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
  5. 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。

其主要缺点如下。

  1. 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
  2. 策略模式造成很多的策略类,增加维护难度。

26.2 策略模式的结构与实现

26.2 .1 策略模式的结构

  1. 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
  2. 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
  3. 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

26.2.2 代码实现

针对不同节日不同的促销活动

关系类图

23种设计模式学习笔记(7)

Strategy

package com.zhuang.strategy;

/**
 * @Classname Strategy
 * @Description 定义共同接口
 * @Date 2021/3/31 15:29
 * @Created by dell
 */

public interface Strategy {
    void show();
}

StrategyA

package com.zhuang.strategy;

/**
 * @Classname StrategyA
 * @Description 定义具体策略角色 每个节日的具体促销活动
 * @Date 2021/3/31 15:29
 * @Created by dell
 */

public class StrategyA implements Strategy {

    @Override
    public void show() {
        System.out.println("A促销 买一送一");
    }
}

StrategyB

package com.zhuang.strategy;

/**
 * @Classname StrategyB
 * @Description 定义具体策略角色 每个节日的具体促销活动
 * @Date 2021/3/31 15:30
 * @Created by dell
 */

public class StrategyB implements Strategy {

    @Override
    public void show() {
        System.out.println("B促销 满100减20");
    }
}

StrategyC

package com.zhuang.strategy;

/**
 * @Classname StrategyC
 * @Description 定义具体策略角色 每个节日的具体促销活动
 * @Date 2021/3/31 15:30
 * @Created by dell
 */

public class StrategyC implements Strategy {

    @Override
    public void show() {
        System.out.println("C促销 满500元可兑换小礼品");
    }
}

SalesMan

package com.zhuang.strategy;

/**
 * @Classname SalesMan
 * @Description 定义环境角色 用于连接上下文 把促销活动推销给顾客
 * @Date 2021/3/31 15:32
 * @Created by dell
 */

public class SalesMan {

    //持有抽象策略角色的引用
    private Strategy strategy;

    public SalesMan(Strategy strategy) {
        this.strategy = strategy;
    }

    public Strategy getStrategy() {
        return strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    //展示促销活动
    public void salesManShow() {
        strategy.show();
    }
}

Client

package com.zhuang.strategy;

/**
 * @Classname Client
 * @Description 策略模式 测试类
 * @Date 2021/3/31 15:34
 * @Created by dell
 */

public class Client {
    public static void main(String[] args) {
        SalesMan salesMan = new SalesMan(new StrategyA());
        //儿童节
        salesMan.salesManShow();

        System.out.println("=======================");
        //劳动节
        salesMan.setStrategy(new StrategyB());
        salesMan.salesManShow();

        System.out.println("=======================");
        //端午节
        salesMan.setStrategy(new StrategyC());
        salesMan.salesManShow();
    }
}

23种设计模式学习笔记(7)

26.3 策略模式应用场景

  • 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。
  • 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。
  • 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。
  • 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。
  • 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。

26.4 JDK源码解析

Comparator 中的策略模式。在Arrays类中有一个 sort() 方法,如下:

public class Arrays{
    public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (c == null) {
            sort(a);
        } else {
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
    }
}

Arrays就是一个环境角色类,这个sort方法可以传一个新策略让Arrays根据这个策略来进行排序。就比如下面的测试类。

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

        Integer[] data = {12, 2, 3, 2, 4, 5, 1};
        // 实现降序排序
        Arrays.sort(data, new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1]
    }
}

这里我们在调用Arrays的sort方法时,第二个参数传递的是Comparator接口的子实现类对象。所以Comparator充当的是抽象策略角色,而具体的子实现类充当的是具体策略角色。环境角色类(Arrays)应该持有抽象策略的引用来调用。那么,Arrays类的sort方法到底有没有使用Comparator子实现类中的 compare() 方法吗?让我们继续查看TimSort类的 sort() 方法,代码如下:

class TimSort<T> {
    static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
                         T[] work, int workBase, int workLen) {
        assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;

        int nRemaining  = hi - lo;
        if (nRemaining < 2)
            return;  // Arrays of size 0 and 1 are always sorted

        // If array is small, do a "mini-TimSort" with no merges
        if (nRemaining < MIN_MERGE) {
            int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
            binarySort(a, lo, hi, lo + initRunLen, c);
            return;
        }
        ...
    }   
        
    private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,Comparator<? super T> c) {
        assert lo < hi;
        int runHi = lo + 1;
        if (runHi == hi)
            return 1;

        // Find end of run, and reverse range if descending
        if (c.compare(a[runHi++], a[lo]) < 0) { // Descending
            while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
                runHi++;
            reverseRange(a, lo, runHi);
        } else {                              // Ascending
            while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)
                runHi++;
        }

        return runHi - lo;
    }
}

上面的代码中最终会跑到 countRunAndMakeAscending() 这个方法中。我们可以看见,只用了compare方法,所以在调用Arrays.sort方法只传具体compare重写方法的类对象就行,这也是Comparator接口中必须要子类实现的一个方法。

27,责任链模式

27.1 责任链模式的定义和特点

责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

注意:责任链模式也叫职责链模式。

在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。所以责任链将请求的发送者和请求的处理者解耦了。

责任链模式是一种对象行为型模式,其主要优点如下。

  1. 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
  2. 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
  3. 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
  4. 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
  5. 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

其主要缺点如下。

  1. 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
  2. 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
  3. 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

27.2 责任链模式的结构与实现

27.2.1 责任链模式的结构

  1. 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
  2. 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  3. 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

27.2.1 代码实现

开发一个请假流程控制系统。请假一天以下的假只需要小组长同意即可;请假1天到3天的假还需要部门经理同意;请求3天到7天还需要总经理同意才行

关系类图

23种设计模式学习笔记(7)

LeaveRequest

package com.zhuang.responsibility;

/**
 * @Classname LeaveRequest
 * @Description 请假条
 * @Date 2021/3/31 16:21
 * @Created by dell
 */

public class LeaveRequest {
    //姓名
    private String name;
    // 请假天数
    private int num;
    // 请假内容
    private String content;

    public LeaveRequest(String name, int num, String content) {
        this.name = name;
        this.num = num;
        this.content = content;
    }

    public String getName() {
        return name;
    }

    public int getNum() {
        return num;
    }

    public String getContent() {
        return content;
    }

}

Handler

package com.zhuang.responsibility;

/**
 * @Classname Handler
 * @Description 用一句话描述类的作用
 * @Date 2021/3/31 16:23
 * @Created by dell
 */

public abstract class Handler {
    protected final static int NUM_ONE = 1;
    protected final static int NUM_THREE = 3;
    protected final static int NUM_SEVEN = 7;

    //该领导处理的请假天数区间
    private int numStart;
    private int numEnd;


    //领导上还有领导
    private Handler nextHandler;

    //设置请假天数范围
    public Handler(int numStart) {
        this.numStart = numStart;
    }

    //设置请假天数范围
    public Handler(int numStart, int numEnd) {
        this.numStart = numStart;
        this.numEnd = numEnd;
    }

    //设置上级领导
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    //提交请假条
    public final void submit(LeaveRequest leaveRequest) {
        if (this.numStart == 0) {
            return;
        }
        //请假天数达到领导处理要求
        if (leaveRequest.getNum() >= this.numStart) {
            this.handleLeave(leaveRequest);

            //如果还有上级 并且请假天数超过当前领导的处理范围
            if (this.nextHandler != null && leaveRequest.getNum() > numEnd) {
                //继续提交
                this.nextHandler.submit(leaveRequest);
            } else {
                System.out.println("流程结束!!!");
            }
        }
    }

    //各级领导处理请假条方法
    protected abstract void handleLeave(LeaveRequest leave);

}

GroupLeader

package com.zhuang.responsibility;

/**
 * @Classname GroupLeader
 * @Description 小组长类
 * @Date 2021/3/31 16:33
 * @Created by dell
 */

public class GroupLeader extends Handler {
    //1-3天的假
    public GroupLeader() {
        super(Handler.NUM_ONE, Handler.NUM_THREE);
    }

    @Override
    protected void handleLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "!");
        System.out.println("小组长审批通过:同意!");
    }
}

Manager

package com.zhuang.responsibility;

/**
 * @Classname Manager
 * @Description 部门经理类
 * @Date 2021/3/31 16:36
 * @Created by dell
 */

public class Manager extends Handler {
    //3-7天的假
    public Manager() {
        super(Handler.NUM_THREE, Handler.NUM_SEVEN);
    }

    @Override
    protected void handleLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "!");
        System.out.println("部门经理审批通过:同意!");
    }
}

GeneralManager

package com.zhuang.responsibility;

/**
 * @Classname GeneralManager
 * @Description 总经理类
 * @Date 2021/3/31 16:38
 * @Created by dell
 */

public class GeneralManager extends Handler{
    //7天以上的假
    public GeneralManager() {
        super(Handler.NUM_THREE, Handler.NUM_SEVEN);
    }

    @Override
    protected void handleLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "!");
        System.out.println("总经理审批通过:同意!");
    }
}

Client

package com.zhuang.responsibility;

/**
 * @Classname Client
 * @Description 责任链模式 测试类
 * @Date 2021/3/31 16:39
 * @Created by dell
 */

public class Client {
    public static void main(String[] args) {
        //请假条
        LeaveRequest leave = new LeaveRequest("小庄", 3, "出去旅游");

        //各位领导
        Manager manager = new Manager();
        GroupLeader groupLeader = new GroupLeader();
        GeneralManager generalManager = new GeneralManager();

        /*
        小组长上司是经理 经理上司是总经理
         */
        groupLeader.setNextHandler(manager);
        manager.setNextHandler(generalManager);

        //提交
        groupLeader.submit(leave);

    }
}

23种设计模式学习笔记(7)

27.3 责任链模式的应用场景

  1. 多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。
  2. 可动态指定一组对象处理请求,或添加新的处理者。
  3. 需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/140735.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!