『重构--改善既有代码的设计』读书笔记----Hide Delegate

所谓委托关系,就是一个类对于另一个类来说纯粹作为接口转发,即客户通过一个委托类去调用另一个对象。直白的委托关系就是委托类直接返回出目标类给客户调用,这个关系很麻烦,因为委托关系的变动就会影响客户端的代码。隐秘的委托关系很健康,当你完全隐藏之后,你委托关系的变化只会发生在委托类的内部,从而不会去影响客户。

封装是面向对象最关键的特征之一。他意味着系统的每个对象都应该尽可能少的了解系统的其他部分,这样带来的好处就是一旦发生了变化之后,需要了解到这一变化的对象就比较少,这也就意味着你需要改动的代码可以很少,让变化可以更加容易的进行。

在C++中你可以光明正大的把字段声明为public,但你应该还是尽量去隐藏这种字段,公开暴露这种字段带来的麻烦可以很多,应该尽量使用protected或者private。随着你开发经验的日渐丰富,你会发现有很多别的东西也可以进行封装。

如果客户需要通过一个服务对象(委托对象)从而得到另一个对象去调用另一个对象的函数,那么客户就必须要知道这一层委托关系,万一委托关系发生变化,客户也得相应变化。你可以在服务对象上放置一个简单的委托函数,将委托关系隐藏起来,从而去除这种依赖。这样一来,如果以后委托关系发生变化,变化也只被限制在服务对象中,不会涉及到客户。对于某些或全部客户,你可能会发现,有必要先使用Extract Class,一旦你对所有客户都隐藏了关系,就不再需要在服务对象中公开被委托对象了。

做法:

  • 对于每一个委托关系中的函数,在服务对象中建立一个简单的委托函数。
  • 调整客户,另他只调用服务对象提供的函数。
  • 每次调整后进行编译,测试。
  • 如果将来不再有任何客户需要显示去获得受托类,那么你就可以彻底移除服务对象中的相关访问函数。
  • 编译,测试。

例子:

class Person
{
    Department *department() const
    {
        return m_department;
    }

    void setDepartment(Department *value)
    {
        m_department = value;
    }

    private:
        Department *m_department;
};

class Department
{
    public:
        Department(Person *person) :
            m_manager(person)
        {
        }
        Person *manager() const
        {
            return m_manager;
        }
    private:
        QString m_chargeCode;
        Person *m_manager;
};

我们可以看到有Person和Department这两个类,我们来看下客户端代码,如果我有一个Person,我想要去获取他的manager,我们就必须先调用得到他的department然后再去调用mana

manager = john->department()->manager();

可以看到,这种调用方式无疑暴露了客户端代码对于Department类的工作原理,我们可以得到原来是Department用来跟踪经理信息的这条逻辑。这样无疑增加了客户代码和Department之间的耦合,要消除这种耦合我们就必须Hide Delegate在Person中建立委托函数

class Person
{
    public:
        Person *manager()
        {
            m_department->manager();
        }
};

然后我们修改客户端代码,让他转而调用新函数。

manager = john->manager();

可以看到,经过这一次修改之后,客户端代码对Department一无所知,这样无论我Person类内部与Department之间进行何种改变,我客户端代码都是稳定的。甚至如果我们完成了对Department的所有函数的委托之后,并相应修改了Person的所有客户,我就可以移除Person中对Department的访问函数了。

ger

posted @ 2014-12-16 10:11  Ricky.K  阅读(1217)  评论(2编辑  收藏  举报