《重构--改善既有代码的设计》--在对象之间搬移特性(7)

一、Move Method(搬移函数)

在A类中有一个A函数与B类中进行更多交流或者被B类调用,可以将A函数变为委托函数,然后移除A函数。

做法:

1、检查源类中字段与函数,考虑是否被搬移。

2、检查源类的子类和父类,看看是否有该函数的其他声明。

3、在目标类中声明这个函数。

4、将源函数的代码复制到目标函数中。

5、编译目标类。

6、决定如何从源函数正确引用目标对象。

7、修改源函数,将当作委托函数。

8、将源类中的源函数替换为目标函数。

9、编译、测试。

范例:

 class Account
    {
        private AccountType _type;
        private int _daysOverdrawn;

        public double OverdraftCharge()
        {
            if (_type.IsPremium())
            {
                double result = 10;
                if (_daysOverdrawn > 7)
                    result += (_daysOverdrawn - 7) * 0.85;
                return result;
            }
            else
                return _daysOverdrawn * 1.75;            
        }

        public double BankCharge()
        {
            double result = 4.5;
            if (_daysOverdrawn > 0)
                result += OverdraftCharge();
            return result;
        }       
    }

将OverdraftCharge()复制到AccountType类中.

class AccountType
    {
        public bool IsPremium()
        {
            return true;
        }

    <span style="color:#ff0000;">    public double OverdraftCharge(int daysOverdrawn)
        {
            if (IsPremium())
            {
                double result = 10;
                if (daysOverdrawn > 7)
                    result += (daysOverdrawn - 7) * 0.85;
                return result;
            }
            else
                return daysOverdrawn * 1.75;
        }
</span>    }

替换Account类中的OverdraftCharge(),并将其删除。

class Account
    {
        private AccountType _type;
        private int _daysOverdrawn;

        public double BankCharge()
        {
            double result = 4.5;
            if (_daysOverdrawn > 0)
                result += <span style="color:#ff0000;">_type.OverdraftCharge(_daysOverdrawn);
</span>            return result;
        }       
    }


 二、Move Field(搬移字段)

类A中某个字段被B类的更多的用到,把该字段搬移到B类中。

做法:

1、如果字段是public,使用Encapsulate Field将它封装。

2、编译、测试。

3、在目标类中建立与源类中相同的字段,并使用属性get/set。

4、编译目标类。

5、如何在源类中引用目标类。

6、删除源字段。

7、将引用的源字段替换成目标字段。

8、编译、测试。

 三、Extract Class(提炼类)

某个类做了应该由两个类做的事,建立新类,将相关字段和函数从旧类中搬移到新类。

做法:

1、决定类的责任。

2、建立新类,把责任从旧类中分离出来。

3、从旧类访问新类的连接关系。

4、对于字段,运用Move Field搬移。

5、编译、测试。

6、使用Move Method先搬移低层函数,然后高层函数。

7、编译、测试。

8、检查,精简每个类的接口。

9、决定是否公开新类。

    class Person
    {
        private string _name;
        private string _officeAreaCode;
        private string _officeNumber;

        public string Name
        {
            get { return _name; }
        }

        public string OfficeAreaCode
        {
            get { return _officeAreaCode; }
            set { _officeAreaCode = value; }
        }

        public string OfficeNumber
        {
            get { return _officeNumber; }
            set { _officeNumber = value; }
        }

        public string GetTelephoneNumber()
        {
            return "(" + _officeAreaCode + ")" + _officeNumber;
        }
    }

 添加一个新类。并把字段与函数搬移到新类中。

 class TelephoneNumber
    {
        private string _officeAreaCode;     
        private string _officeNumber;

        public string OfficeAreaCode
        {
            get { return _officeAreaCode; }
            set { _officeAreaCode = value; }
        }

        public string OfficeNumber
        {
            get { return _officeNumber; }
            set { _officeNumber = value; }
        }
    }

修改旧类。

class Person
    {        
        private string _name;
        private TelephoneNumber _telephoneNumber = new TelephoneNumber();

        public string Name
        {
            get { return _name; }
        }    

        public string GetTelephoneNumber()
        {
            return "(" + _telephoneNumber.OfficeAreaCode + ")" + _telephoneNumber.OfficeNumber;
        }
    }


 四、Inline Class(将类内联化)

某个类没有做太多事情,将这个类的所有特性搬移到另一个类中,然后移除原类。

1、在目标类身上声明源类的public协议,并将其中所有函数委托至源类。

2、修改所有源类引用点,改而引用目标类。

3、编译、测试。

4、运用Move Method和Move Field,将源类的特性全部搬移到目标类。

五、Hide Delegate(隐藏委托)

客户通过一个委托类来调用另一个对象。在服务类上建立客户所需的所有函数,用以隐藏委托关系。

1、对于每一个委托关系中的函数,在服务对象端建立一个简单的委托函数。

2、调整客户,令它只调用服务对象提供的函数。

3、每次调整后,编译并测试。

4、如果将来不再有任何客户需要取用图7-1的Delegate(受托类),便可移除服务对象中的相关访问函数。

5、编译、测试。

 class Department
    {
        private string _chargeCode;
        private Person _manager;

        public Department(Person manager)
        {
            _manager = manager;
        }

        public Person Person
        {
            get { return _manager; }
        }
    }

 

class Person
    {
        Department _department;

        public Department Department
        {
            get { return _department; }
            set { _department = value; }
        }   
 
       <span style="color:#ff0000;"> public Person GetManager()
        {
            return _department.Person;
        } </span>   
    }


如果客户希望知道某人的经理是谁,他必须先取得Department对象。即: Person p = new Person();  Department d = new Department(p);  

这样的编码就是对客户揭露了Department的工作原理,隐藏Department,可以减少耦合。在Person中建立一个简单的委托函数。

六、Remove Middle Man(移除中间人)

某个类做了过多的简单委托动作,让客户直接调用受托类。

1、建立一个函数,用以获得受托对象。

2、对于每个委托函数,在服务类中删除该函数,并让需要调用该函数的客户转为调用受托对象。

3、处理每个委托函数后,编译、测试。

七、Introduce Foreign Method(引用外加函数)

 你需要为提供服务的类增加一个函数,但你无法修改这个类。

在客户类中建立一个函数,并以第一参数形式传入一个服务类实例。

1、在客户类中建立一个函数,用来提供你需要的功能。

2、以服务类实例作为函数的第一个参数。

3、将该函数注释为:“外加函数(Foreign Method),应在服务类实现”。

DateTime newStart = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day + 1);

变为一个外加函数:

private static DateTime NextDay()
{
       return new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day + 1);
}

八、Introduce Local Extension(引入本地扩展)

 你需要为提供服务的类增加一个函数,但你无法修改这个类。

建立一个新类,使它包含这些额外函数。让这个扩展品成为源类的子类或包装类。

1、建立一个扩展类,将它作为原始类的子类或包装类。

2、在扩展类中加入转型构造函数。

3、在扩展类加入新特性。

4、根据需要,将源对象替换为扩展对象。

5、将针对原始类定义的所有外加函数搬移到扩展类中。

 

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值