Fork me on GitHub

重构手法之在对象之间搬移特性【2】

返回总目录

本小节目录

3Extract Class(提炼类)

概要

某个类做了应该由两个类做的事。

建立一个新类,将相关的字段和函数从旧类搬移到新类。

动机

如果一个类中有大量的函数和数据,这个类往往太大而且不易理解。这时候就需要考虑哪些部分可以分离出去,并将它们分离到一个单独的类中。

如果发现子类化只影响类的部分特性,或如果某些特性需要以一种方式来子类化,某些特性则需要以另一种方式子类化,这也意味着需要分解原来的类。

范例

先看一个简单的Person类。

class Person
{

    public string Name { get; set; }

    public string OfficeAreaCode { get; set; }

    public string OfficeNumber { get; set; }

    public string GetTelephoneNumber()
    {
        return $"({OfficeAreaCode})-{OfficeNumber}";
    }
}

在这里,我们可以将与电话号码有关的行为分离到一个独立的类中。

首先,定义一个TelePhoneNumber类表示“电话号码”:

class TelePhoneNumber{}

然后,在Person类中建立从Person到TelePhoneNumber的连接:

 private TelePhoneNumber _phoneNumber = new TelePhoneNumber();

现在运用Move Field移动属性,并运用Move Method将相关函数移动到TelePhoneNumber类中。

class Person
{
    private TelePhoneNumber _phoneNumber = new TelePhoneNumber();

    public string Name { get; set; }

    public string GetTelephoneNumber()
    {
        return _phoneNumber.GetTelephoneNumber();
    }

}
class TelePhoneNumber
{
    public string OfficeAreaCode { get; set; }

    public string OfficeNumber { get; set; }

    public string GetTelephoneNumber()
    {
        return $"({OfficeAreaCode})-{OfficeNumber}";
    }
}

小结

类的单一原则表示:一个类应该是一个清楚的抽象,处理一些明确的责任。如果一个类做了两个类的事,那它就该被提炼了。

4Inline Class(将类内联化)

概要

某个类没有做太多事情。

将这个类的所有特性搬移到另一个类中,然后移除原类。

动机

Inline Class和Extract Class正好相反。如果一个类不再承担足够责任、不再有单独存在的理由,那么就将其塞进另一个类中。

范例

第3节中我们提炼出一个TelePhoneNumber类,现在我们将其塞回Person中。

class Person
{
    private TelePhoneNumber _phoneNumber = new TelePhoneNumber();

    public string Name { get; set; }

    public string GetTelephoneNumber()
    {
        return _phoneNumber.GetTelephoneNumber();
    }


}
class TelePhoneNumber
{
    public string OfficeAreaCode { get; set; }

    public string OfficeNumber { get; set; }

    public string GetTelephoneNumber()
    {
        return $"({OfficeAreaCode})-{OfficeNumber}";
    }
}

首先,在Person中声明TelePhoneNumber的所有public的函数。

class Person
{
    private TelePhoneNumber _phoneNumber = new TelePhoneNumber();

    public string Name { get; set; }

    public string OfficeAreaCode { get; set; }

    public string OfficeNumber { get; set; }
    public string GetTelephoneNumber()
    {
        return _phoneNumber.GetTelephoneNumber();
    }

    public TelePhoneNumber GetOfficeTelePhoneNumber()
    {
        return _phoneNumber;
    }

}

现在,我们要做的就是:找出所有使用TelePhoneNumber的地方,让它们使用Person的接口。于是,下列代码:

Person martin=new Person();
martin.GetOfficeTelePhoneNumber().OfficeAreaCode = "781";

就变成了:

Person martin=new Person();
martin.OfficeAreaCode = "781";

最后,反复使用Move MethodMove Field,直到TelePhoneNumber类不复存在。

小结

如果一个类无所事事,那么这就是一种坏味道——Lazy Class。遇到这种类,我们应该毫不犹豫的为它举行“葬礼”,将它塞进其他类中。

 

To Be Continued……

posted @ 2017-11-23 08:59  NaYoung  阅读(616)  评论(0编辑  收藏  举报