简体   繁体   English

重构对象以使用装饰器模式

[英]Refactor object to use decorator pattern

Using a third party API, I've written wrapper classes for their objects.使用第三方 API,我为它们的对象编写了包装类。 The obvious/standard way would be this:明显/标准的方式是这样的:

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);
    }
}

However, Foo 's get methods are expensive.但是, Fooget方法很昂贵。 So instead, I do this:所以相反,我这样做:

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);
    }
}

However, for testing reasons, I want to be able to have all the functionality without needing an instance of the third party API.但是,出于测试原因,我希望能够在不需要第三方 API 实例的情况下拥有所有功能。 So I want to refactor the existing wrapper version where the third party API functionality is just a decorator:所以我想重构现有的包装器版本,其中第三方 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);
    }
}

Obviously, my real classes are a lot more complicated;显然,我真正的课程要复杂得多; I fear it will be easy to make a mistake.我怕很容易犯错。 I suppose that's what tests are for, but... the questions:我想这就是测试的目的,但是......问题:

  • Primary question In Fowler's Refactoring , each refactoring has a step-by-step process to ensure correctness.主要问题在 Fowler's Refactoring 中,每次重构都有一个分步过程以确保正确性。 Is there one for this process?这个过程有吗?
  • Does this sort of refactoring have a name?这种重构有名字吗? "Extract Decorator"? “提取装饰器”?
  • Does it even make sense to do this (vs. just making a test class from scratch)这样做是否有意义(与从头开始制作测试类相比)
  • Is there an IDE that can do this?有没有可以做到这一点的IDE? I'm currently using Eclipse 4.3.1我目前正在使用 Eclipse 4.3.1

For a true Decorator/Adapter, the Adapter should have the same interface so your wrapper methods get/setMyParam() should be get/setParam() and if possible you should implement the 3rd party interface if it exists.对于真正的装饰器/适配器,适配器应该具有相同的接口,因此您的包装方法get/setMyParam()应该是get/setParam()并且如果可能,您应该实现第 3 方接口(如果存在)。

Code should not be able to tell the difference between your wrapper and the original from an API perspective.代码应该无法从 API 的角度区分您的包装器和原始包装器之间的区别。

Now onto your questions:现在回答你的问题:

Primary question: In Fowler's Refactoring, each refactoring has a step-by-step process to ensure correctness.主要问题:在 Fowler's Refactoring 中,每次重构都有一个分步过程以确保正确性。 Is there one for this process?这个过程有吗?

Yes, Joshua Kerievsky's Refactoring to Patterns calls this "Extract Adapter" and there is a step by step example.是的,Joshua Kerievsky 的Refactoring to Patterns称之为“提取适配器”,并且有一个循序渐进的例子。 I can't find an exact code example online but the UML before/after is Here我在网上找不到确切的代码示例,但之前/之后的 UML 在 这里

Does this sort of refactoring have a name?这种重构有名字吗? "Extract Decorator"? “提取装饰器”?

As stated before it's called Extract Adapter如前所述,它被称为提取适配器

Does it even make sense to do this (vs. just making a test class from scratch)这样做是否有意义(与从头开始制作测试类相比)

Maybe depends on your usecase.也许取决于您的用例。

Is there an IDE that can do this?有没有可以做到这一点的IDE? I'm currently using Eclipse 4.3.1我目前正在使用 Eclipse 4.3.1

You can use Eclipse's refactoring tools to perform each step but I would hesitate to try to do a complicated refactoring like you are hinting that you have in a single button push, even if a tool existed that would let you.您可以使用 Eclipse 的重构工具来执行每个步骤,但我会犹豫是否尝试进行复杂的重构,就像您暗示只需按一下按钮一样,即使存在可以让您使用的工具。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM