【问题标题】:Refactor object to use decorator pattern重构对象以使用装饰器模式
【发布时间】:2014-04-02 14:47:45
【问题描述】:

使用第三方 API,我为其对象编写了包装类。明显/标准的方式是这样的:

public class WrapperFoo implements MyWrapper {
    private Foo f;

    public WrapperFoo(Foo f) {
        this.foo = foo;
    }

    public int getMyParam() {
        return f.getParam();
    }

    public void setMyParam(int param) {
        if(param < 0) throw new IllegalArgumentException("Param must not be negative!");
        f.setParam(param);
    }
}

但是,Fooget 方法很昂贵。所以相反,我这样做:

public class WrapperFoo implements MyWrapper {
    private Foo f;
    private int myParam;

    public WrapperFoo(Foo f) {
        this.foo = foo;
    }

    public int getMyParam() {
        return param;
    }

    public void setMyParam(int param) {
        if(param < 0) throw new IllegalArgumentException("Param must not be negative!");
        this.param = param;
        f.setParam(param);
    }
}

但是,出于测试原因,我希望能够拥有所有功能而不需要第三方 API 的实例。所以我想重构现有的包装器版本,其中第三方 API 功能只是一个装饰器:

public class WrapperImpl implements MyWrapper {
    private int myParam;

    public int getMyParam() {
        return myParam;
    }

    public void setMyParam(int param) {
        if(param < 0) throw new IllegalArgumentException("Param must not be negative!");
        this.myParam = param;
    }
}

public class WrapperFoo implements MyWrapper {
    private MyWrapper backing;
    private Foo f;

    public WrapperFoo(MyWrapper backing, Foo f) {
        this.backing = backing;
        this.foo = f;
    }

    public int getMyParam() {
        return backing.getMyParam();
    }

    public void setMyParam(int param) {
        backing.setMyParam(int param);
        f.setParam(param);
    }
}

显然,我的真实课程要复杂得多;恐怕很容易出错。我想这就是测试的目的,但是......问题:

  • 主要问题 在 Fowler 的Refactoring 中,每个重构都有一个分步过程来确保正确性。这个过程有没有一个?
  • 这种重构有名称吗? “提取装饰器”?
  • 这样做是否有意义(与从头开始创建测试类相比)
  • 是否有可以执行此操作的 IDE?我目前使用的是 Eclipse 4.3.1

【问题讨论】:

  • 我不肯定,但这闻起来像mockito

标签: java refactoring decorator


【解决方案1】:

对于真正的装饰器/适配器,适配器应该具有相同的接口,因此您的包装器方法get/setMyParam() 应该是get/setParam(),并且如果可能,您应该实现第 3 方接口(如果存在)。

从 API 的角度来看,代码应该无法区分您的包装器和原始包装器。

现在回答你的问题:

首要问题:在 Fowler 的重构中,每次重构都有一个逐步的过程来确保正确性。这个过程有没有一个?

是的,Joshua Kerievsky 的 Refactoring to Patterns 称此为“提取适配器”,并且有一个分步示例。我在网上找不到确切的代码示例,但之前/之后的 UML 是 Here

这种重构有名字吗? “提取装饰器”?

如前所述,它被称为提取适配器

这样做是否有意义(相对于从头开始创建一个测试类)

可能取决于您的用例。

是否有可以做到这一点的 IDE?我目前正在使用 Eclipse 4.3.1

您可以使用 Eclipse 的重构工具来执行每个步骤,但我会犹豫是否尝试进行复杂的重构,就像您暗示您只需按一下按钮一样,即使存在可以让您使用的工具。

【讨论】:

  • 感谢您的回答。第三方接口是不存在的,其实就是get(int idTag),不过我觉得跟讨论没关系。
  • 另外:Extract Adapter你给我的名字使我能够正确地用谷歌搜索。
猜你喜欢
  • 2021-03-28
  • 1970-01-01
  • 2013-02-17
  • 2013-05-07
  • 1970-01-01
  • 1970-01-01
  • 2021-08-16
  • 2014-02-20
  • 1970-01-01
相关资源
最近更新 更多