关系密切的设计模式(二)

策略模式 + 桥接模式

假设一个场景(需求),需要在一个分布式系统的每个组件里,向基础服务注册自己。然而基础服务要求各个组件根据组件自身不同的位置,其注册策略也不同,如下表:

位置 注册要求
位置一 1、计算并缓存本地数据摘要值(需要提供查询摘要接口);2、将摘要值通过接口注册给基础服务A
位置二 1、计算并缓存本地数据摘要值(需要提供查询摘要接口);2、将摘要值通过接口注册给基础服务B
位置三 1、计算并缓存本地数据摘要值(需要提供查询摘要接口);2、将摘要值通过接口注册给基础服务A;3、将摘要值通过接口注册给基础服务B
位置四 1、计算并缓存本地数据摘要值(需要提供查询摘要接口);

此情况下,很明确使用策略模式不仅会简化问题、增强封装性,还能在今后再出现“位置X”的时候,不需要修改老代码。但仅使用策略模式,四个位置的实现类中,会不同程度的出现重复代码。直接想到的解决方法是,将计算摘要和调用注册接口写成公共函数,放在基类中。

本文想提供另一个思路,此思路基于一个设计原则:“少用继承,多用组合”。即使用桥接模式,重复用到的函数,不直接在基类中实现,而是再定义一个IMPL类实现这些功能,并将此类作为基类的一个成员。

enum BASE_SERVICE {
	SRV_A,
	SRV_B
};
class CompImpl {
public:
	CompImpl(const char* db_data, unsigned int data_len);
	void CalcDigest(){...} // 这里假设摘要定长
	bool RegDigest(BASE_SERVICE base_service){...}
	char* GetDigest(){...}
private:
    char digest[DIG_LEN];
};

// 接口类
class IPosReg {
public:
	IPosReg(const char* db_data, unsigned int data_len) : impl_(db_data, data_len){impl_.CalcDigest();}
	virtual ~IPosReg(){}
	virtual bool RegDigest() = 0;
	virtual char* GetDigest();
protected:
	CompImpl impl_;
};

// 以下为实现四个位置的子类
class CPos1Reg : public IPosReg {
public:
	CPos1Reg(const char* db_data, unsigned int data_len) : IPosReg(db_data, data_len){}
	virtual bool RegDigest(){return impl_.RegDigest(SRV_A);}
	vitrual char* GetDigest(){return impl_.GetDigest();}
};

class CPos2Reg : public IPosReg {
public:
	CPos2Reg(const char* db_data, unsigned int data_len) : IPosReg(db_data, data_len){}
	virtual bool RegDigest(){return impl_.RegDigest(SRV_B);}
	vitrual char* GetDigest(){return impl_.GetDigest();}
};

class CPos3Reg : public IPosReg {
public:
	CPos1Reg(const char* db_data, unsigned int data_len) : IPosReg(db_data, data_len){}
	virtual bool RegDigest(){
		bool ret = impl_.RegDigest(SRV_A);
		if (!ret)
			return ret;
		return impl_RegDigest(SRV_B);
	}
	vitrual char* GetDigest(){return impl_.GetDigest();}
};

class CPos4Reg : public IPosReg {
public:
	CPos1Reg(const char* db_data, unsigned int data_len) : IPosReg(db_data, data_len){}
	virtual bool RegDigest(){return false;}
	vitrual char* GetDigest(){return impl_.GetDigest();}
};

enum REG_POSITION{
	REG_POS_1,
	REG_POS_2,
	REG_POS_3,
	REG_POS_4
};
IPosReg* CreatePosIns(REG_POSITION reg_pos, const char* db_data, unsigned int data_len){
	switch (reg_pos)
	{
		case REG_POS_1:
			return new CPos1Reg(db_data, data_len);
			...
	}
}

猜你喜欢

转载自blog.csdn.net/svp_Charles/article/details/82829930