Chain of Responsibility(职责链)模式

本文介绍了职责链模式的基本概念,包括模式意图、参与者及应用场景。通过一个网络应用中充值返利的例子,展示了如何使用职责链模式处理不同用户等级的返利请求,解释了如何构建和配置处理链,以及如何通过这种方式降低耦合度和增强灵活性。用户代码演示了不同等级用户充值时的返利计算,显示了模式的有效性。
摘要由CSDN通过智能技术生成


前言

        本周五参加了Chain of Responsibility(职责链)模式研讨会,本文的目的是对这个模式的总结和分享,希望对需要学习这个设计模式的同学有所帮助。本文一共分为两个部分,第一个部分是职责链模式的基础知识总结;第二个部分是职责链模式的一个例子分享。

一、职责链模式总结

        

1、模式意图

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

2、参与者

Handler
-- 定义一个处理请求的接口;
-- 实现后继链;
ConcreteHandler
-- 处理它所负责的请求;
-- 可访问它的后继者;
-- 如果可以请求,则处理并返回,否则将请求转发给它的后继者;
Client
-- 向链上的具体处理者对象提交请求;

3、结构、适用性及效果

结构图:

在这里插入图片描述

适用性:
1、有多个对象可以处理一个请求,哪个对象处理请求运行时自动确定;
2、你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
3、可处理一个请求的对象的集合需要动态指定时;
效果:
1、降低耦合度;职责链模式使得一个对象不用知道是哪一个对象处理它的请求。对象仅需要知道该请求会被正确的处理。接收者和发送者都没有对方的明确的信息,且链中的对象不需要知道链的结构。
2、增强了给对象指派职责的灵活性;当在对象中分派职责时,职责链给你更多的灵活性。你可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的那些职责。
3、不保证请求被处理;既然一个请求没有明确的接收者,那么就不能保证它一定会被处理;该请求可能一直到链的末端都得不到处理。一个请求也可能因该链没有被正确配置而得不到处理。

二、职责链模式应用示例

1、用例背景描述

         职责链模式经常用于网络开发,下面举的一个例子是关于充值返利方面的应用。在一个网络应用中,我们可以对用户进行等级划分,等级越高的用户,充值返利越多,等级越低的用户,充值返利则相对较少。

2、用例结构图

在这里插入图片描述

RebateHandler:充值返利接口类; RebateHandlerVip0:用户等级为0的具体充值返利实现类; RebateHandlerVip1:用户等级为1的具体充值返利实现类; RebateHandlerVip2:用户等级为2的具体充值返利实现类;

3、类说明

1、RebateHandler :定义抽象充值返利接口,后继节点维护接口及业务相关公共接口:
class RebateHandler {
public:
    RebateHandler(int level);
    //充值返利接口,根据输入用户对象及充值金额,返回返利后的总充值额。
    virtual double getRebate(User* user, double count);  
    //设置后继节点  
    void set_next_handler(RebateHandler* handler);

protected:
	//根据用户等级获取返利比率
	double get_level_rate(int level);
	//获取后继节点
    RebateHandler* get_next_handler();
    //设置相应等级的返利比率
    void set_level_rate(int level, double rate);
    //获取当前处理节点的用户等级
    int get_level();
    
private:
    std::map<int,double> m_rate_table;
    RebateHandler* m_next_handler;
    int m_lever;
};

RebateHandler::RebateHandler(int level) : m_lever(level){
    m_next_handler = NULL;
}

double RebateHandler:: getRebate(User* user, double count) {
    if (m_next_handler != NULL) {
        return m_next_handler->getRebate(user, count);
    } else {
        double rate = this->get_level_rate(user->get_level());
        return rate*count;
    }
}

double RebateHandler::get_level_rate(int level) {
    if (m_rate_table.find(level) != m_rate_table.end()) {
        return m_rate_table[level];
    } else {
        return 1.0;
    }
}

RebateHandler* RebateHandler::get_next_handler() {
    return m_next_handler;
}

void RebateHandler::set_next_handler(RebateHandler *handler) {
    m_next_handler = handler;
}

int RebateHandler::get_level() {
    return m_lever;
}

void RebateHandler::set_level_rate(int level, double rate) {
    m_rate_table[level] = rate;
}
2、RebateHandlerVip0 ~ RebateHandlerVip2 ·:具体处理节点类,实现具体的充值返利功能:
class RebateHandlerVip0 : public RebateHandler {
public:
    RebateHandlerVip0();
    virtual double getRebate(User* user, double count);
};

RebateHandlerVip0::RebateHandlerVip0() : RebateHandler(0) {
    this->set_level_rate(this->get_level(), 1.0);
}

double RebateHandlerVip0::getRebate(User *user, double count) {
    (void)user;
    double rate = this->get_level_rate(this->get_level());
    return rate*count;
}

class RebateHandlerVip1 : public RebateHandler {
public:
    RebateHandlerVip1();
    virtual double getRebate(User* user, double count);
};

RebateHandlerVip1::RebateHandlerVip1() : RebateHandler(1) {
    this->set_level_rate(this->get_level(), 1.1);
}

double RebateHandlerVip1::getRebate(User* user, double count) {
    if (user->get_level() >= this->get_level()) {
        double rate = this->get_level_rate(this->get_level());
        return rate*count + 10;
    } else {
        RebateHandler* next_handler = get_next_handler();
        if (next_handler != NULL) {
            return next_handler->getRebate(user, count);
        } else {
            return RebateHandler::getRebate(user, count);
        }
    }
}

class RebateHandlerVip2 : public RebateHandler {
public:
    RebateHandlerVip2();
    virtual double getRebate(User* user, double count);
};

RebateHandlerVip2::RebateHandlerVip2() : RebateHandler(2) {
    this->set_level_rate(this->get_level(), 1.2);
}

double RebateHandlerVip2::getRebate(User *user, double count) {
    if (user->get_level() >= this->get_level()) {
        double rate = this->get_level_rate(this->get_level());
        return rate*count + 20;
    } else {
        RebateHandler* next_handler = get_next_handler();
        if (next_handler != NULL) {
            return next_handler->getRebate(user, count);
        } else {
            return RebateHandler::getRebate(user, count);
        }
    }
}

3、User :用户类,用于发送请求,处理节点会根据用户的等级做相应的处理。
class User {
public:
    User(int level);
    int get_level();
    void set_level(int level);

private:
    int m_level;
};

User::User(int level) : m_level(level) {

}

User::get_level() {
    return m_level;
}

void User::set_level(int level) {
    m_level = level;
}

4、用户代码。三个不同等级的处理节点及三个不同等级的用户,它们充值相同的金额,但返利数量不同,用户等级越高,返利越多,反之则越少。
RebateHandler* header = NULL;

    // 处理节点
    RebateHandlerVip2* vip2 = new RebateHandlerVip2();
    RebateHandlerVip1* vip1 = new RebateHandlerVip1();
    RebateHandlerVip0* vip0 = new RebateHandlerVip0();

    // 处理链
    header = vip2;
    vip2->set_next_handler(vip1);
    vip1->set_next_handler(vip0);


    // 用户
    User* vip2_player = new User(2);
    User* vip1_player = new User(1);
    User* vip0_player = new User(0);

	//充值100
    double vip2_count = header->getRebate(vip2_player, 100);
    double vip1_count = header->getRebate(vip1_player, 100);
    double vip0_count = header->getRebate(vip0_player, 100);

	//充值返利后实际额度
    printf("vip2_count : %f\n", vip2_count);
    printf("vip1_count : %f\n", vip1_count);
    printf("vip0_count : %f\n", vip0_count);

5、运行结果。

在这里插入图片描述


总结

         根据上述例子,我们可以看到,对于相同的请求,处理请求的节点可以不同,这样就把请求对象和处理对象完全解耦,增加了程序的灵活性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值