zoukankan      html  css  js  c++  java
  • 【重构.改善既有代码的设计】7、在对象之间搬移特性(如何优化类)

    7、在对象之间搬移特性

    Move Method(搬移函数)

    描述:
    有个函数与其所驻class之外的另一个class进行更多交流:调用后者,或被后者调用。
    在该函数最常引用(指涉)的class中建立一个有着类似行为的新函数。将旧函数变成一个单纯的委托函数(delegating method),或是将旧函数完全移除。

    原因:
    高耦合。依赖情节。

    注意:
    1、在迁移的时候,要考虑函数用到的属于原class的变量及其他函数,是否也应该迁移,这会是更大的收获。
    2、不是所有变量都需要移动的,不能移动的作为调用参数也是可以的。

    Move Field(搬移值域)

    描述:
    你的程序中,某个field(值域〕被其所驻class之外的另一个class更多地用到。
    在target class 建立一个new field,修改source field的所有用户,令它们改用此new field。

    Extract Class(提炼类)

    某个class做了应该由两个classes做的事。
    建立一个新class,将相关的值域和函数从旧class搬移到新class。

    原因:
    1、单一职责原则,一个变化只应该影响一个类,多种变化应该影响多个类。
    2、改善并发,可以缩小锁的范围,精确锁的粒度。

    使用场景:1、方法太多,2、变量太多。这样的class往往太大而不易理解。此时你需要考虑哪些部分可以分离出去,并将它们分离到一个单独的class中。

    后续:
    1、决定这个类要不要对外暴露?如果不暴露,可以采用委托方式。

    Inline Class(将类内联化)

    你的某个class没有做太多事情(没有承担足够责任)。
    将class的所有特性搬移到另一个class中,然后移除原class。

    与Extract Class 相反。

    Hide Delegate(隐藏「委托关系」)

    客户直接调用其server object(服务对象)的delegate class。

    在server端(某个class〕建立客户所需的所有函数,用以隐藏委托关系(delegation)。

    委托有好有坏,还是要根据情况决定是否要隐藏委托。

    Remove Middle Man(移除中间人)

    某个class做了过多的简单委托动作(simple delegation)。

    让客户直接调用delegate(受托类)。

    “Hide Delegate(隐藏「委托关系」)”的逆操作。

    Introduce Foreign Method(引入外加函数)

    你正在使用一个class,它真的很好,为你提供了你想要的所有服务。
    而后,你又需要一项新服务,这个class却无法供应。
    于是你开始咒骂:「为什么不能做这件事?」如果可以修改源码,你便可以自行添加一个新函数; 
    如果不能,你就得在客户端编码,补足你要的那个函数。

    其实就是把外面的方法装饰一下提供一个符合自己要求的新方法。

    如果需要多个函数,或者多个类需要这个函数,那就用下一个方法:Introduce Local Extension(引入本地扩展)

    Introduce Local Extension(引入本地扩展)

    你所使用的server class需要一些额外函数,但你无法修改这个class。

    建立一个新class,使它包含这些额外函数。让这个扩展品成为source class的subclass (子类〕或wrapper(外覆类)。

    1、使用Subclass(子类)

    这个容易的。继承后新加函数就好了。

    2、使用wrapper(外覆类)

    这种方案是在wrapper类中,聚合一个原始类,然后为原始类所有用到的函数提供委托函数。这个就会很烦。

    原作者的总结

    在对象的设计过程中,「决定把责任放在哪儿」即使不是最重要的事,也是最重要的事之一。
    我使用对象技术已经十多年了,但还是不能一开始就保证做对。
    这曾经让我很烦恼,但现在我知道,在这种情况下,我可以运用重构(refactoring),改变自己原先的设计。

    常常我可以只运用 Move Method 和Move Field 简单地移动对象行为,就可以解决这些问题。
    如果这两个重构手法都需要用到,我会首先使用Move Field,再使用Move Method。

    class往往会因为承担过多责任而变得臃肿不堪。这种情况下,我会使用Extract Class 将一部分责任分离出去。
    如果一个class变得太「不负责任」,我就会使用Inline Class 将它融入另一个class。
    如果一个class使用了另一个class,运用Hide Delegate 将这种关系隐藏起来通常是有帮助的。
    有时候隐藏delegate class会导致拥有者的接口经常变化,此时需要使用Remove Middle Man。

    本章的最后两项重构——Introduce Foreign Method 和Introduce Local Extension ——比较特殊。
    只有当我不能访问某个class的源码,却又想把其他责任移进这个不可修改的class时,我才会使用这两个重构手法。
    如果我想加入的只是一或两个函数,我会使用Introduce Foreign Method;如果不止一两个函数,我就使用Introduce Local Extension。

    我的总结

    相对于第6章讲的是解决长函数的问题,本章讲的是不合理类的优化。

    优化手段如下:
    1、职责过多: 
    1.1、包含了本属于其他类的函数:Move Method(搬移函数)
    1.2、包含了本属于其他类的值:Move Field(搬移值域)
    1.3、其他类还没有创建:Extract Class(提炼类)
    2、职责过少:Inline Class(将类内联化)
    3、聚合对象(中间人)接口过多/接口常变,维护困难:Remove Middle Man(移除中间人)
    4、聚合对象(中间人)接口简单稳定,但访问多,需隐藏:Hide Delegate(隐藏「委托关系」)
    5、少数sdk常用功能的扩展:Introduce Foreign Method(引入外加函数)
    6、多数sdk常用功能的扩展:Introduce Local Extension(引入本地扩展)

  • 相关阅读:
    记录一些经常被忽略的结论
    Eclipse 各种问题解决记录
    Feign 动态URL 解决记录
    Nacos 启动失败
    多git账号配置解决方案
    记一次java.lang.StackOverflowError
    StringBuilder 以及 StringBuffer默认大小与扩容
    MySQL索引背后的数据结构及原理
    我没有高并发项目经验,但是面试的时候经常被问到高并发、性能调优方面的问题,有什么办法可以解决吗?
    istio 学习之 手动注入sidecar
  • 原文地址:https://www.cnblogs.com/aoyihuashao/p/10383673.html
Copyright © 2011-2022 走看看