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


    返回总目录

    本小节目录

    5Hide Delegate(隐藏“委托关系”)

    概要

    客户通过一个委托关系来调用另一个对象。

    在服务类上建立客户所需的所有函数,用以隐藏委托关系。

    动机

    如果某个客户先通过服务对象的字段或者属性得到另一个对象,然后调用后者的函数,那么客户就必须知晓这一层委托关系。万一委托关系发生变化,客户也得相应变化。你可以在服务对象上放置一个简单的委托关系,将委托关系隐藏起来,从而去除这种依赖。这么一来,即便将来发生委托关系上的变化,变化也将被限制在服务对象中,不会波及客户。

    范例

    看下面代表“人”的Person类和代表“部门”的Department类:

    class Person
    {
        public Department Department { get; set; }
    
    }
    class Department
    {
        private string _chargeCode;
    
        public Person Manager { get; set; }
    
        public Department(Person manager)
        {
            Manager = manager;
        }
    
    }

    如果客户想知道某人的经理是谁,他必须先取得Department对象:

    Person john = new Person();
    var manager = john.Department.Manager;

    这样的编码就对客户揭露了Department的工作原理,于是客户知道:Department用以追踪“经理”这条消息。如果对客户隐藏Department,可以减少耦合。为此,我们在Person中建立一个简单的委托函数:

    class Person
    {
        public Department Department { get; set; }
    
        public Person GetManager()
        {
            return Department.Manager;
        }
    }

    现在,我得修改Person的所有客户,让它们改用新函数:

    Person john = new Person();
    var manager = john.GetManager();

    修改完所有的客户之后,就可以将Person的Department的get设为私有的了。

    public Department Department { private get; set; }

    当然了也可以将属性改为私有字段:

    private Department _department;

    小结

    “封装”即使不是对象的最关键特征,也是最关键特征之一。“封装”意味着对象都应该尽可能少了解系统的其他部分。如此一来,一旦发生变化,需要了解这一变化的对象就会较少。

    6Remove Middle Man(移除中间人)

    概要

    某个类做了过多的简单委托动作。

    让客户直接调用委托类。

    动机

    第5节我们说到“封装受托对象”的好处。但是这样的封装也是要付出代价的,即:每当客户要使用受托类的新特性时,就必须在服务端添加一个简单委托函数。随着受托类的特性越来越多,这一过程将非常痛苦。服务类完全成了“中间人”,这时候就需要让客户直接调用受托类。

    范例

    还是来看上面的“人与部门”的例子。

    class Person
    {
        public Department Department { private get; set; }
    
        public Person GetManager()
        {
            return Department.Manager;
        }
    }
    class Department
    {
        private string _chargeCode;
    
        public Person Manager { get; set; }
    
        public Department(Person manager)
        {
            Manager = manager;
        }
    
    }

    为了找出某人的经理,客户代码可能这样写:

    Person john = new Person();
    var manager = john.GetManager();

    像这样,使用封装和Department都很简单。但如果大量函数都这么做,就不得不在Person之间安置大量的委托行为。这就是该移除中间人的时候了。

    首先在Person中建立一个函数用于获得受托对象:

    public Department GetDepartment()
    {
        return Department;
    }

    然后逐一处理每个委托函数。针对每一个这样的函数,找出通过Person使用的函数,并对它进行修改,使它首先获得受托对象,然后直接使用后者:

    var manager = john.GetDepartment().Manager;

    然后就可以删除Person的GetManager()函数。

    小结

    很难说什么程度的隐藏才是最合适的。随着系统的变化,“合适的隐藏程度”这个尺度也在相应改变。昨天你感觉恰如其分的封装,今天就可能显得很笨拙。还好,我们有了Hide Delegate和Remove Middle Man,因为我们可以在系统运行过程中不断进行调整。

    重构的意义在于:永远不必说对不起——只要把出问题的地方修补好就行了。

    To Be Continued……

  • 相关阅读:
    Android框架之Volley与Glide
    美团点餐—listview内部按钮点击事件
    Android之MaterialDesign应用技术2-仿支付宝上滑搜索框缓慢消失
    Android之MaterialDesign应用技术
    Android之Bmob移动后端云服务器
    Java设计模式总汇二---MVC、中介者设计模式
    Java设计模式总汇一 (适配器、单例、静态代理、简单工厂设计模式)
    Android数据绑定技术二,企业级开发
    再次强调完成的定义(DoD)
    在远程 CSM 课程中体验线上工作坊
  • 原文地址:https://www.cnblogs.com/liuyoung/p/7862260.html
Copyright © 2020-2023  润新知