标签:style blog http ar color 使用 sp strong on
在面向对象中,对于类这个概念我们应该有一个清晰的责任认识,就是每个类应该只有一个变化点,每个类的变化应该只受到单一的因素,即每个类应该只有一个明确的责任。当然了,说时容易做时难,很多人可能都会和我一样,一开始建立类的时候信心满满,牢记SRP原则,但随着开发进度的不断进行,很有可能你会给你原本设计好的类增加新字段或者增加新函数,对于少量的增加你可能会因为麻烦,考虑不去单独做一个新类来分解。久而久之,你这个类会变得越来越臃肿,所掌管的责任也会越来越多。这样的类往往还有大量的数据和函数,往往太大而不易理解。这个时候你就应该考虑哪些东西可以单独分离出去作为一个单独的类。如果你发现某些数据和某些函数总是一起出现,某些数据经常同时变化甚至彼此相依,这就表示你应该把它们都分离出去。当然,作者也提到了一个比较好的技巧,就是你自己问自己,如果你单独搬移了某些函数和字段,会发生什么事情,其他函数和字段是否会变得没有意义。
另外一种情况就是往往就是在开发后期出现的给类做子类化的问题。如果你发现子类化只影响类的部分特性,或如果你发现某些特性需要用一种子类化方式,某些特性需要另外一种子类化方式,这就意味着你需要分解原来的类了。
做法:
例子:
class Person { public: QString name() { return m_name; } QString telephoneNumber() { return m_officeAreaCode + m_officeNumber; } QString officeAreaCode() { return m_officeAreaCode; } void setOfficeAreaCode(const QString &value) { m_officeAreaCode = value; } QString officeNumber() { return m_officeNumber; } void setOfficeNumber(const QString &value) { m_officeNumber = value; } private: QString m_name; QString m_officeAreaCode; QString m_officeNumber; };
看完这个例子我们可以发现我们完全可以把跟电话号码相关的特性放到一个单独的“电话”类中去。首先我们定义一个电话类来表示电话号码这个概念。
class TelephoneNumber { };
接下来我们要做的就是建立从Person到TelephoneNumber的连接,即给Person增加一个字段来保存TelephoneNumber对象
class Person { private: TelephoneNumber m_telephoneNumber; };
接下来我们就可以运用Move Field来搬移跟电话相关的字段,在这里是m_officeAreaCode和m_officeNumber,首先我们来移动m_officeAreaCode我们可以得到
class TelephoneNumber { QString officeAreaCode() { return m_officeAreaCode; } void setOfficeAreaCode(const QString &value) { m_officeAreaCode = value; } private: QString m_officeAreaCode; };
这是目标类经过Move Field之后的样子
class Person { public: QString telephoneNumber() { return officeAreaCode() + m_officeNumber; } QString officeAreaCode() { return m_telephoneNumber.officeAreaCode(); } void setOfficeAreaCode(const QString &value) { m_telephoneNumber.setOfficeAreaCode(value); } private: TelephoneNumber m_telephoneNumber; };
这是旧类经过Move Field之后关于officeAreaCode先关引用的改变。然后我可以移动其他字段,并运用Move Method把相关函数移动到TelephoneNumber类中
class Person { public: QString name() { return m_name; } QString telephoneNumber() { return m_telephoneNumber.telephoneNumber(); } TelephoneNumber telephoneClass() { return m_telephoneNumber; } private: TelephoneNumber m_telephoneNumber; QString m_name; }; class TelephoneNumber { QString telephoneNumber() { return m_officeAreaCode + m_officeNumber; } QString officeAreaCode() { return m_officeAreaCode; } void setOfficeAreaCode(const QString &value) { m_officeAreaCode = value; } QString officeNumber() { return m_officeNumber; } void setOfficeNumber(const QString &value) { m_officeNumber = value; } private: QString m_officeAreaCode; QString m_officeNumber; };
完成这些之后我们需要考虑需要不需要向用户公开这个新类,我可以让旧类做新类的委托类来完全隐藏新类,也可以直接向用户公开。如果考虑公开,你就需要去考虑别名问题,考虑返回值对象和引用对象对自己所带来的后果。
面对这种问题,有如下几种选择:
Extract Class是改善并发程序的一种常用技术,如何理解?简单来说他可以让你对分解后的两个类进行分别加锁,如果你有这方面的需求你可以这么做。当然也存在危险性,如果你要确保两个对象同时锁定,这里面又牵扯到了事务问题,需要使用其他类型的共享锁,这是一个复杂的领域,比起一般情况需要更繁重的机制,虽然事务很有实用性,但在这里如果你手动编写事务管理程序则会超出大多数程序员的职责范围。
『重构--改善既有代码的设计』读书笔记----Extract Class
标签:style blog http ar color 使用 sp strong on
原文地址:http://www.cnblogs.com/rickyk/p/4162776.html