重构 — 改善既有的类图设计 条款12:消除聚合内部的返回参数的复制

重构 — 改善既有的类图设计 条款12:消除聚合内部的返回参数的复制

黄国强 2008-10-07

上文说到,CInner 如果本身很大的话,会有一个复制开销。这个依然可以通过设计来解决方法很多,比如写一个句柄类引入引用计数就可以。我这里介绍的是我自己发明的一种方法,自认为比较简单。
首先我们把 CInner 变成一个不变的值对象。如下面的示例中,所有的set函数都取消。

// 负责表示一个聚合类内部的类
class CInner
{
...
public:
void SetVal(double dVal); // 取消这个函数
double GetVal(void)const;
private:
...
};

CAggregate 修改后的代码实现请看下面。

// 负责表示聚合类
class CAggregate
{
...
public:
boost::shared_ptr<CInner> GetInner(void)const // 此处返回值修改成返回一个boost::shared 指针,没有复制开销
{
return m_pInner;
}

void SetInner(boost::shared<CInner> pNewVal)
{
m_pInner.reset(new CInner(*pNewVal.get())); // 此处调用了 CInner 的复制构造函数重新分配一个新的对象并赋值给 m_pInner
}


private:
boost::shared_ptr<CInner> m_pInner;
...
};

由于 CInner 是一个不变的值对象,所以即使持有 boost::shared<CInner> 指针也无法修改 CAggregate 内部的 m_pInner 成员,从而完整性得到保证。

图一为引入 boost::shared_ptr 模板重构后的图。关于 boost::shared_ptr 的详细请参阅 boost 库的相关资料,本文不作展开。

图一

相关文章

迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图...
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,...
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定...
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个...
命令模式(Command)命令模式(Command)[Action/Transactio...
生成器模式(Builder)生成器模式(Builder)意图:将一个对...