C++之多层 if-else-if 结构优化(二)

相关系列文章

C++之多层 if-else-if 结构优化(一)

C++之多层 if-else-if 结构优化(二)

C++之多层 if-else-if 结构优化(三)

设计模式之责任链模式

设计模式之工厂模式

设计模式之策略模式

目录

7.使用责任链模式进行结构优化

8.利用模板元编程的萃取原理来优化

9.利用策略模式+工厂模式来优化


7.使用责任链模式进行结构优化

        责任链模式,Chain of responsibility,是GoF中的behavior pattern行为模式中的一种,在所有的行为模式中,设计的准则都为:使用对象的组合而不是对象的继承。责任链模式所描述的是:与其从已有的类中继承新的类,不如让你的类指向一个你要使用的已经存在的类。该模式用于解耦发送请求的客户与处理请求的对象,实现方式为持有一系列的handler对象,每个对象都能处理特定的请求,如果某个handler不能处理该请求,它将请求传递给链中的下一个对象。在链的末端,会有一个或多个通用的(generic)handler,用于对请求的默认处理。

  该模式为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

        责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请
求,并返回相应的结果
,其通用类图如下图所示。

根据责任链模式,设计类图如下:

代码如下:

#define  MAX_PARAM   0x7FFFFFFF
class IMessageEntityBase
{
public:
	virtual int  func(int num) = 0;
};

class CMessageEntity1 : public IMessageEntityBase
{
public:
	explicit CMessageEntity1(IMessageEntityBase* pNext) : m_pNext(pNext) {}
	int  func(int num) override {
		if (num < 0) {
			qDebug() << "类CMessageEntity1 调用函数 -- func() " << "   传递参数: num: " << num;
			return num;
		}
		return m_pNext ? m_pNext->func(num) : MAX_PARAM;
	}
private:
	IMessageEntityBase* m_pNext;
};

class CMessageEntity2 : public IMessageEntityBase
{
public:
	explicit CMessageEntity2(IMessageEntityBase* pNext) : m_pNext(pNext) {}
	int  func(int num) override {
		if (num > 0 && num <= 10) {
			qDebug() << "类CMessageEntity2 调用函数 -- func() " << "   传递参数: num: " << num;
			return num;
		}
		return m_pNext ? m_pNext->func(num) : MAX_PARAM;
	}
private:
	IMessageEntityBase* m_pNext;
};

class CMessageEntity3 : public IMessageEntityBase
{
public:
	explicit CMessageEntity3(IMessageEntityBase* pNext) : m_pNext(pNext) {}
	int  func(int num) override {
		if (num > 10 && num <= 100) {
			qDebug() << "类CMessageEntity3 调用函数 -- func() " << "   传递参数: num: " << num;
			return num;
		}
		return m_pNext ? m_pNext->func(num) : MAX_PARAM;
	}
private:
	IMessageEntityBase* m_pNext;
};

class CMessageEntity4 : public IMessageEntityBase
{
public:
	explicit CMessageEntity4(IMessageEntityBase* pNext) : m_pNext(pNext) {}
	int  func(int num) override {
		if (num > 100 && num <= 1000) {
			qDebug() << "类CMessageEntity4 调用函数 -- func() " << "   传递参数: num: " << num;
			return num;
		}
		return m_pNext ? m_pNext->func(num) : MAX_PARAM;
	}
private:
	IMessageEntityBase* m_pNext;
};

class CMessageEntity5 : public IMessageEntityBase
{
public:
	explicit CMessageEntity5(IMessageEntityBase* pNext) : m_pNext(pNext) {}
	int  func(int num) override {
		if (num > 1000 && num <= 10000) {
			qDebug() << "类CMessageEntity5 调用函数 -- func() " << "   传递参数: num: " << num;
			return num;
		}
		return m_pNext ? m_pNext->func(num) : MAX_PARAM;
	}
private:
	IMessageEntityBase* m_pNext;
};

class CMessageEntityOverRange : public IMessageEntityBase
{
public:
	explicit CMessageEntityOverRange(IMessageEntityBase* pNext) : m_pNext(pNext) {}
	int  func(int num) override {
		if (num >= 10000) {
			qDebug() << "类CMessageEntityOverRange 调用函数 -- func() " << "   传递参数: num: " << num;
			return num;
		}
		return m_pNext ? m_pNext->func(num) : MAX_PARAM;
	}
private:
	IMessageEntityBase* m_pNext;
};

class CTestMessageEntity
{
public:
	void setFunctor(IMessageEntityBase* pFunctor) {
		m_functor = pFunctor;
	}
	int func(int num)
	{
		return m_functor->func(num);
	}
private:
	IMessageEntityBase* m_functor;
};

int  main()
{
	std::unique_ptr<IMessageEntityBase> pOverRanage(new CMessageEntityOverRange(nullptr));
	std::unique_ptr<IMessageEntityBase> pFunctor5(new CMessageEntityOverRange(pOverRanage.get()));
	std::unique_ptr<IMessageEntityBase> pFunctor4(new CMessageEntityOverRange(pFunctor5.get()));
	std::unique_ptr<IMessageEntityBase> pFunctor3(new CMessageEntityOverRange(pFunctor4.get()));
	std::unique_ptr<IMessageEntityBase> pFunctor2(new CMessageEntityOverRange(pFunctor3.get()));
	std::unique_ptr<IMessageEntityBase> pFunctor1(new CMessageEntityOverRange(pFunctor2.get()));

	CTestMessageEntity  test;
	test.setFunctor(pFunctor1.get());

	int result = test.func(5);
	result = test.func(80);
	result = test.func(1500);
	result = test.func(8000);

	return 0;
}

8.利用模板元编程的萃取原理来优化

        萃取的实现方法:模板偏特化后使用using对偏特化的参数取别名;使用static成员;使用参数化萃取。

        萃取的目的是实现 标签派发

        在我的博客 std::apply源码分析-CSDN博客 的 std::__invoke 实现部分也用到了类型萃取技术,可以去看看。

先看一下没有优化之前的代码:

MessageField.h

template <messageType TYPE, typename T, typename = std::enable_if_t<std::is_same<T,std::uint32_t>::value||
                                                                   std::is_same<T,std::int32_t>::value ||
                                                                   std::is_same<T,double>::value ||
                                                                   std::is_same<T,std::uint64_t>::value ||
                                                                   std::is_same<T,std::uint16_t>::value ||
                                                                   std::is_same<T,float>::value>>
class CMessageStringTField : public CMessageStringField
{
    using _base = CMessageStringField;

public:
    explicit CMessageStringTField(){ }
    CMessageStringTField(const CMessageStringTField& other)
        : _base(other){
    }
    virtual ~CMessageStringTField(){}

public:
    IMessageField* clone(const IMessageField* pSrc) const override{
        return new CMessageStringTField(*dynamic_cast<const CMessageStringTField*>(pSrc));
    }
    messageType type() const override{
        return TYPE;
    }
    bool isMultiValue() const override{
        return true;
    }
    //和客户端交互的接口,kv一对一和一对多类型
    bool getPacketValue(std::vector<std::uint64_t>& values) const override{
        std::vector<T> data;
        //[1] 将string转为T
        if constexpr(std::is_same<T, std::uint64_t>::value){
            gSplitString<T>(m_value, ::atoll, data);
        }else if constexpr(std::is_same<T, std::uint32_t>::value){
            gSplitString<T>(m_value, ::atol, data);
        }else if constexpr(std::is_same<T, std::uint16_t>::value){
            gSplitString<T>(m_value, ::atol, data);
        }else if constexpr(std::is_same<T, std::int32_t>::value){
            gSplitString<T>(m_value, ::atoi, data);
        }else if constexpr(std::is_same<T, float>::value){
            gSplitString<T>(m_value, ::atof, data);
        }else if constexpr(std::is_same<T, double>::value){
            gSplitString<T>(m_value, ::atof, data);
        }else{
            assert(0);
        }

        //[2] 将T转为std::uint64_t
        for(auto& it : data){
            values.push_back(transTToPUInt64(it));
        }
        return true;
    }
    //kv一对多类型
    bool setPacketValue(const std::vector<std::uint64_t>& values) override{
        m_value.clear();
        for (int i = 0; i < values.size(); i++){
            m_value += numConvertString(transPUInt64ToT<T>(values[i]));
            if (i != values.size()-1){
                m_value += ",";
            }
        }
        return true;
    }
    ...
};

        里面的if constexpr(...) 表达式,编译器在编译时期使用编译时期表达式决定是否使用if语句或then部分或else部分(如果有的话)。如果其中一个分支条件成立,则另一部分(如果有的话)被丢弃,这样也就不会生成被丢弃部分的代码。但是,这并不意味着被丢弃的部分完全被忽略,它就像未使用模板的代码一样检查语法等。

        gSplitString的实现如下:

template <typename T, typename FUNC = T(const char*),
         typename = std::enable_if_t<std::is_arithmetic<T>::value>>
void gSplitString(const std::string& data, FUNC&& func, std::vector<T>& vecValue)
{
    const char * split = ",";
    std::unique_ptr<char[]> temp(new char[data.size()+1]);
    memcpy(temp.get(), data.c_str(), data.size());
    temp[data.size()] = '\0';

    // 以逗号为分隔符拆分字符串
    char *p = strtok(temp.get(), split);

    while(p != NULL)
    {
        vecValue.push_back((T)func(p));
        p = strtok(NULL, split);
    }
}

在类成员函数getPacketValue中根据T的类型,调用不同的转换函数进行处理,基本都是字符串向数值类型转换,比较多的if constexpr 使得代码比较难看,扩展性也不好;那有没有什么办法根据T就是直接推导出使用那个转换函数呢,于是类型萃取技术就是粉墨登场了,其实类型萃取技术也不是什么高深的技术,在STL中很多地方都用到了类型萃取技术,如:迭代器iterator中iterator_category, 通过它可以提取到的类型有五种,如下:

  • input iterator:只读
  • output iterator:只写
  • forward iterator:允许写入,在此迭代器所形成的区间上进行读写操作
  • bidirectional iterator:可以双向移动
  • random access iterator:支持指针的所有算数操作

然后STL的算法模块就根据 iterator_category 的不同调用不同的算法函数。

上面的代码我们也是根据这个原理来优化,优化后的代码如下:

MessageStringTFieldAssist.h

namespace xyLinkCorePrivate {
    struct _tag_int64_value {};
    struct _tag_uint32_value {};
    struct _tag_int32_value {};
    struct _tag_double_value {};

    template <typename T>
    void _splitString(_tag_int64_value, const std::string& value, std::vector<T>& data){
        gSplitString<T>(value, ::atoll, data);
    }
    template <typename T>
    void _splitString(_tag_uint32_value, const std::string& value, std::vector<T>& data){
        gSplitString<T>(value, ::atol, data);
    }
    template <typename T>
    void _splitString(_tag_int32_value, const std::string& value, std::vector<T>& data){
        gSplitString<T>(value, ::atoi, data);
    }
    template <typename T>
    void _splitString(_tag_double_value, const std::string& value, std::vector<T>& data){
        gSplitString<T>(value, ::atof, data);
    }

    #define  IS_INT64_VALUE(T)             (std::is_same<T,std::uint64_t>::value||std::is_same<T,std::int64_t>::value)
    #define  IS_SIGNED_LESS32_VALUE(T)     (std::is_same<T,std::uint32_t>::value||std::is_same<T,std::uint16_t>::value)
    #define  IS_UNSIGNED_LESS32_VALUE(T)   (std::is_same<T,std::int32_t>::value||std::is_same<T,std::int16_t>::value)

    template <typename T>
    struct _value_type_category{
        //typename千万不能省略,2023.12.14调试了大半天都没有搞明白是咋回事,一直编译报错
        using type = typename std::conditional<IS_INT64_VALUE(T), _tag_int64_value,
                                               typename std::conditional<IS_SIGNED_LESS32_VALUE(T), _tag_uint32_value,
                                                                         typename std::conditional<IS_UNSIGNED_LESS32_VALUE(T), _tag_int32_value, _tag_double_value>::type>::type>::type;
    };

    #undef  IS_INT64_VALUE
    #undef  IS_SIGNED_LESS32_VALUE
    #undef  IS_UNSIGNED_LESS32_VALUE
}

MessageField.h

#define IS_SUIT_TYPE(T)  (  std::is_same<T,std::uint32_t>::value||    \
                            std::is_same<T,std::int32_t>::value ||    \
                            std::is_same<T,double>::value ||          \
                            std::is_same<T,std::uint64_t>::value ||   \
                            std::is_same<T,std::uint16_t>::value ||   \
                            std::is_same<T,float>::value )

template <messageType TYPE, typename T, typename = std::enable_if_t<IS_SUIT_TYPE(T)>>
//template <messageType TYPE, typename T, std::enable_if_t<IS_SUIT_TYPE(T),int> = 0>
class CMessageStringTField : public CMessageStringField
{
    using _base = CMessageStringField;

public:
    explicit CMessageStringTField(){ }
    CMessageStringTField(const CMessageStringTField& other)
        : _base(other){
    }
    virtual ~CMessageStringTField(){}

public:
    IMessageField* clone(const IMessageField* pSrc) const override{
        return new CMessageStringTField(*dynamic_cast<const CMessageStringTField*>(pSrc));
    }
    messageType type() const override{
        return TYPE;
    }
    bool isMultiValue() const override{
        return true;
    }

public:
    //和客户端交互的接口,kv一对一和一对多类型
    bool getPacketValue(std::vector<std::uint64_t>& values) const override{
        static_assert(IS_SUIT_TYPE(T),"T is not std::uint32_t or std::int32_t or float or double or std::uint16_t or std::uint64_t");
        std::vector<T> data;
        //[1] 将string转为T
        using t = typename xyLinkCorePrivate::_value_type_category<T>::type;
        xyLinkCorePrivate::_splitString(t{}, m_value, data);

        //[2] 将T转为std::uint64_t
        for(auto& it : data){
            values.push_back(transTToPUInt64(it));
        }
        return true;
    }
    //kv一对多类型
    bool setPacketValue(const std::vector<std::uint64_t>& values) override{
        m_value.clear();
        for (int i = 0; i < values.size(); i++){
            m_value += numConvertString(transPUInt64ToT<T>(values[i]));
            if (i != values.size()-1){
                m_value += ",";
            }
        }
        return true;
    }
    ...
};

优化代码后,函数getPacketValue的逻辑就比较清晰明了,通俗易懂。

9.利用策略模式+工厂模式来优化

        根据传入参数num的不同,调用不用的处理方法。那么就可以把这个处理流程分成两条线,一条线是处理方法,可以称之为处理策略,另外一条是根据num的不同,生成不同的处理策略,根据我们之前讲解的工厂模式,是不是有点像简单工厂的味道?实际上也是。

        首先,我们把每个条件逻辑代码块,抽象成一个公共的接口,可以得出以下代码:

//抽象策略接口
class IMessageEntityBase
{
public:
	virtual int  func() = 0;
};
//具体策略1
class CMessageEntity1 : public IMessageEntityBase
{
public:
	explicit CMessageEntity1(int num) : m_num(num) {}
	int  func() override {
		qDebug() << "类CMessageEntity1 调用函数 -- func() " << "   传递参数: num: " << m_num;
		return m_num;
	}
private:
	int m_num;
};
//具体策略2
class CMessageEntity2 : public IMessageEntityBase
{
public:
	explicit CMessageEntity2(int num) : m_num(num) {}
	int  func() override {
		qDebug() << "类CMessageEntity2 调用函数 -- func() " << "   传递参数: num: " << m_num;
		return m_num;
	}
private:
	int m_num;
};
//具体策略3
class CMessageEntity3 : public IMessageEntityBase
{
public:
	explicit CMessageEntity3(int num) : m_num(num) {}
	int  func() override {
		qDebug() << "类CMessageEntity3 调用函数 -- func() " << "   传递参数: num: " << m_num;
		return m_num;
	}
private:
	int m_num;
};
//具体策略4
class CMessageEntity4 : public IMessageEntityBase
{
public:
	explicit CMessageEntity4(int num) : m_num(num) {}
	int  func() override {
		qDebug() << "类CMessageEntity4 调用函数 -- func() " << "   传递参数: num: " << m_num;
		return m_num;
	}
private:
	int m_num;
};
//具体策略5
class CMessageEntity5 : public IMessageEntityBase
{
public:
	explicit CMessageEntity5(int num) : m_num(num) {}
	int  func() override {
		qDebug() << "类CMessageEntity5 调用函数 -- func() " << "   传递参数: num: " << m_num;
		return m_num;
	}
private:
	int m_num;
};
//具体策略6
class CMessageEntityOverRange : public IMessageEntityBase
{
public:
	explicit CMessageEntityOverRange(int num) : m_num(num) {}
	int  func() override {
		assert(0);
		qDebug() << "类CMessageEntityOverRange 调用函数 -- func() " << "   传递参数: num: " << m_num;
		return -1;
	}
private:
	int m_num;
};

接下来,我们再定义策略工厂类,用来管理具体策略类,如下:

//策略工厂
class CMessageEntityFactory
{
	using R = std::shared_ptr<IMessageEntityBase>;
	using FUNC = std::function<R(int)>;
public:
	explicit CMessageEntityFactory() {
		m_vecFactory.emplace_back([](int num)->R {
			R pMessageEntiry;
			if (num <= 0) {
				pMessageEntiry.reset(new CMessageEntity1(num));
			}
			return pMessageEntiry;
			});
		m_vecFactory.emplace_back([](int num)->R {
			R pMessageEntiry;
			if (num > 0 && num <= 10) {
				pMessageEntiry.reset(new CMessageEntity2(num));
			}
			return pMessageEntiry;
			});
		m_vecFactory.emplace_back([](int num)->R {
			R pMessageEntiry;
			if (num > 10 && num <= 100) {
				pMessageEntiry.reset(new CMessageEntity3(num));
			}
			return pMessageEntiry;
			});
		m_vecFactory.emplace_back([](int num)->R {
			R pMessageEntiry;
			if (num > 100 && num <= 1000) {
				pMessageEntiry.reset(new CMessageEntity4(num));
			}
			return pMessageEntiry;
			});
		m_vecFactory.emplace_back([](int num)->R {
			R pMessageEntiry;
			if (num > 1000 && num <= 10000) {
				pMessageEntiry.reset(new CMessageEntity5(num));
			}
			return pMessageEntiry;
			});
		m_vecFactory.emplace_back([](int num)->R {
			R pMessageEntiry;
			if (num > 10000) {
				pMessageEntiry.reset(new CMessageEntityOverRange(num));
			}
			return pMessageEntiry;
			});
	}
	R create(int num) {
		R temp;
		for (int i = 0; i < m_vecFactory.size(); i++) {
			if (temp = m_vecFactory[i](num)) {
				break;
			}
		}
		return temp;
	}
private:
	std::vector<FUNC> m_vecFactory;
};

使用了策略+工厂模式之后,代码变得简洁多了,如下:

int  main()
{
	CMessageEntityFactory  factory;
	auto pFunctor = factory.create(5);
	auto result = pFunctor->func();

	pFunctor = factory.create(80);
	result = pFunctor->func();

	pFunctor = factory.create(1500);
	result = pFunctor->func();

	pFunctor = factory.create(8000);
	result = pFunctor->func();

	return 0;
}

C++之多层 if-else-if 结构优化(三)-CSDN博客

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值