《重构:改善既有代码的设计》中提到过很多重构方法,关于重新组织数据的方法有8种。本文介绍:
将对象之间的关联由单向改为双向 change unidirectional association to bidirectional
- 名称:将对象之间的关联由单向改为双向 change unidirectional association to bidirectional
- 概要:两个类都需要使用对方特性,但其间只有一条单向连接。添加一个反向指针,并使修改函数能够同时更新两条连接
- 动机:开发初期,会在两个类之间建立一条单向连接,使其引用另一个类。但被引用类需要得到其引用者以便进行某些处理。
- 做法:
- 在被引用类种增加一个字段,用以保存反向指针
- 决定由哪个类--引用端还是被引用端--控制关联关系
- 在被控端建立一个辅助函数,其命名应该清楚指出它的有限用途
- 如果既有的修改函数在控制端,让它负责更新反向指针
- 如果既有的修改函数在被控端,就在控制端建立一个控制函数,并让既有的修改函数调用这个新建的控制函数
- 代码演示
修改之前的代码:
.h
class order;
class customer
{
public:
private:
QSet<order *> m_pOrderSet;
};
class order
{
public:
void setCustomer(const customer &customer);
customer getCustomer() const;
private:
customer m_customer;
};
.cpp
void order::setCustomer(const customer &customer)
{
m_customer = customer;
}
customer order::getCustomer() const
{
return m_customer;
}
修改之后的代码:
哪个类负责控制关联关系呐?
1)如果两者都是引用对象,而其间的关联使“一对多”关系,那么就由“拥有单一引用”的那一方承担“控制者”角色。一个customer可以拥有多个order,就由order来控制关联关系。
2)如果对象使组成另一对象的部件,就由后者负责控制关联关系
如果两者都是应用对象s, 而其间的关联是“多对多”关系,两者都可以。
/.h
#ifndef MAINWINDOWTEST_H
#define MAINWINDOWTEST_H
#include <QMainWindow>
#include <QSet>
class order;
class customer
{
public:
QSet<order *> FriendOrders();
void AddOrder(order * porder);
private:
QSet<order *> m_pOrderSet;
};
class order
{
public:
void setCustomer(customer *customer);
customer* getCustomer() const;
private:
customer *m_pcustomer;
};
#endif // MAINWINDOWTEST_H
//.cpp
void order::setCustomer(customer *customer)
{
if (m_pcustomer != nullptr)
{
m_pcustomer->FriendOrders().remove(this);
}
m_pcustomer = customer;
if (m_pcustomer != nullptr)
{
m_pcustomer->FriendOrders().insert(this);
}
}
customer* order::getCustomer() const
{
return m_pcustomer;
}
QSet<order *> customer::FriendOrders()
{
return m_pOrderSet;
}
void customer::AddOrder(order * porder)
{
//希望在customer中也可以修改
m_pOrderSet.insert(porder);
porder->setCustomer(this);
}