[7] [数据结构] ( 3 ) 职责链 ChainofResposibility

总结

  • GOF定义?
    使多个对象都有机会处理请求,
    从而避免请求的发送者和接收者(handler)之间的耦合关系。
    将这些对象连成一条链,(链表)
    并沿着这条链传递请求,
    直到有一个对象处理它为止.
    .
    运行时再确定哪一个handler可以处理这个request.
    .
    过程像踢皮球一样.


  • 解耦谁?
    将请求的发送者和接受者解耦.


  • 好处?
    添加新的handler或者修改现有的handler,
    不用改动其他handler的代码,
    每一个handler处理特定的任务,
    代码更加模块化.


  • 缺点?
    性能开销大
    调试复杂


  • 场景?
    web框架中间件
    GUI事件处理
    异常处理




java例子1

重构前

package v22_chain_of_responsibility.java;

class Logger {
    public static final int ERROR = 1;
    public static final int DEBUG = 2;
    public static final int INFO = 3;
    private int level;

    public Logger(int level) {
        this.level = level;
    }

    // 处理者
    public void logMessage(int logLevel, String message) {
        // 每次添加新的日志类型, 都需要改动这里的if else.
        if (logLevel == ERROR && logLevel <= level) {
            System.out.println("Error: " + message);
        } else if (logLevel == DEBUG && logLevel <= level) {
            System.out.println("Debug: " + message);
        } else if (logLevel == INFO && logLevel <= level) {
            System.out.println("Info: " + message);
        }
    }
}

public class LoggerDemo1 {
    public static void main(String[] args) {
        Logger logger = new Logger(Logger.INFO);
        // 发送者
        logger.logMessage(Logger.ERROR, "This is an error message");
        logger.logMessage(Logger.DEBUG, "This is a debug message");
        logger.logMessage(Logger.INFO, "This is an info message");
    }
}





重构后

package v22_chain_of_responsibility.java;

abstract class Logger {

    protected int level;
    protected Logger nextLogger;

    public void setNextLogger(Logger nextLogger) {
        this.nextLogger = nextLogger;
    }

    public void logMessage(int logLevel, String message) {
        if (logLevel <= level) {
            write(message);
        } else if (nextLogger != null) {
            nextLogger.logMessage(logLevel, message);
        }
    }

    abstract protected void write(String message);
}

class ErrorLogger extends Logger {
    public ErrorLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Error: " + message);
    }
}

class DebugLogger extends Logger {
    public DebugLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Debug: " + message);
    }
}

class InfoLogger extends Logger {
    public InfoLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Info: " + message);
    }
}

public class LoggerDemo2 {
    public static void main(String[] args) {
        ErrorLogger errorLogger = new ErrorLogger(1);
        DebugLogger debugLogger = new DebugLogger(2);
        InfoLogger infoLogger = new InfoLogger(3);

        errorLogger.setNextLogger(debugLogger);
        debugLogger.setNextLogger(infoLogger);

        errorLogger.logMessage(1, "This is an error message");
        errorLogger.logMessage(2, "This is a debug message");
        errorLogger.logMessage(3, "This is an info message");
    }
}





java例子2

package v22_chain_of_responsibility.java;


// 抽象handler
interface DispenseChain {
    void setNextChain(DispenseChain nextChain);  // 设置下一个接点
    void dispense(Currency currency);            // 派发
}

// request / 货币
class Currency {
    private int amount; // 额度

    public Currency(int amount) {
        this.amount = amount;
    }

    public int getAmount() {
        return amount;
    }
}

// 具体handler 50
class Dollar50Dispenser implements DispenseChain {
    private DispenseChain chain;

    @Override
    public void setNextChain(DispenseChain nextChain) {
        this.chain = nextChain;
    }

    @Override
    public void dispense(Currency currency) {
        if (currency.getAmount() >= 50) { 
            // 面额大于50
            int numberOfNotes = currency.getAmount() / 50; // 计算有几个50面额
            int remainder = currency.getAmount() % 50;     // 计算零头

            // 把50面额的处理掉
            System.out.println("Dispensing " + numberOfNotes + " 50$ note");

            // 如果有零头,进行责任派发
            if (remainder != 0) {
                this.chain.dispense(new Currency(remainder));
            }
        } else {
            // 面额小于50, 直接进行责任派发
            this.chain.dispense(currency);
        }
    }
}

// 具体handler 20
class Dollar20Dispenser implements DispenseChain {
    private DispenseChain chain;

    @Override
    public void setNextChain(DispenseChain nextChain) {
        this.chain = nextChain;
    }

    @Override
    public void dispense(Currency currency) {
        if (currency.getAmount() >= 20) {
            int numberOfNotes = currency.getAmount() / 20;
            int remainder = currency.getAmount() % 20;
            System.out.println("Dispensing " + numberOfNotes + " 20$ note");
            if (remainder != 0) {
                this.chain.dispense(new Currency(remainder));
            }
        } else {
            this.chain.dispense(currency);
        }
    }
}

// 具体handler 10
class Dollar10Dispenser implements DispenseChain {
    private DispenseChain chain;

    @Override
    public void setNextChain(DispenseChain nextChain) {
        this.chain = nextChain;
    }

    @Override
    public void dispense(Currency currency) {
        if (currency.getAmount() >= 10) {
            int numberOfNotes = currency.getAmount() / 10;
            int remainder = currency.getAmount() % 10;
            System.out.println("Dispensing " + numberOfNotes + " 10$ note");
            if (remainder != 0) {
                this.chain.dispense(new Currency(remainder));
            }
        } else {
            this.chain.dispense(currency);
        }
    }
}

// 客户端
public class ATMDispenser {
    private DispenseChain c1;

    public ATMDispenser() {
        // initialize the chain
        this.c1 = new Dollar50Dispenser();
        DispenseChain c2 = new Dollar20Dispenser();
        DispenseChain c3 = new Dollar10Dispenser();

        // 设定责任链
        c1.setNextChain(c2);
        c2.setNextChain(c3);
    }

    public void dispenseMoney(Currency currency) {
        if (currency.getAmount() % 10 != 0) {
            System.out.println("金额应为 10 的倍数.");
            return;
        }

        // process the request
        c1.dispense(currency);
    }

    public static void main(String[] args) {
        ATMDispenser atmDispenser = new ATMDispenser();
        Currency currency = new Currency(370);
        atmDispenser.dispenseMoney(currency);
    }
}





image




image




c++例子

#include <iostream>
#include <string>

using namespace std;

enum class RequestType
{
    REQ_HANDLER1,
    REQ_HANDLER2,
    REQ_HANDLER3
};

class Reqest
{
    string description;
    RequestType reqType;
public:
    Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {}

    RequestType getReqType() const { 
        return reqType; 
    }

    const string& getDescription() const { 
        return description; 
    }
};

class ChainHandler{
    ChainHandler *nextChain;
    void sendReqestToNextHandler(const Reqest & req)
    {
        if (nextChain != nullptr)
            nextChain->handle(req);
    }
protected:
    virtual bool canHandleRequest(const Reqest & req) = 0;
    virtual void processRequest(const Reqest & req) = 0;
public:
    ChainHandler() { 
        nextChain = nullptr; 
    }
    void setNextChain(ChainHandler *next) { 
        nextChain = next; 
    }
    void handle(const Reqest & req){
        if (canHandleRequest(req))
            processRequest(req);
        else
            sendReqestToNextHandler(req);
    }
};


class Handler1 : public ChainHandler{
protected:
    bool canHandleRequest(const Reqest & req) override
    {
        return req.getReqType() == RequestType::REQ_HANDLER1;
    }
    void processRequest(const Reqest & req) override
    {
        cout << "Handler1 is handle reqest: " << req.getDescription() << endl;
    }
};
        
class Handler2 : public ChainHandler{
protected:
    bool canHandleRequest(const Reqest & req) override
    {
        return req.getReqType() == RequestType::REQ_HANDLER2;
    }
    void processRequest(const Reqest & req) override
    {
        cout << "Handler2 is handle reqest: " << req.getDescription() << endl;
    }
};

class Handler3 : public ChainHandler{
protected:
    bool canHandleRequest(const Reqest & req) override
    {
        return req.getReqType() == RequestType::REQ_HANDLER3;
    }
    void processRequest(const Reqest & req) override
    {
        cout << "Handler3 is handle reqest: " << req.getDescription() << endl;
    }
};

int main(){
    Handler1 h1;
    Handler2 h2;
    Handler3 h3;
    h1.setNextChain(&h2);
    h2.setNextChain(&h3);

    Reqest req("process task ... ", RequestType::REQ_HANDLER3);
    h1.handle(req);
    return 0;
}





image




image




posted @ 2023-12-04 21:09  qwertzxc  阅读(19)  评论(0)    收藏  举报