干燥这些类的最佳方法是什么,除了构造函数之外的所有内容都重复

发布于 2024-09-09 00:28:31 字数 1860 浏览 2 评论 0原文

因此,我进行了一些重构,现在我的两个类除了构造函数之外看起来完全相同。

这些类包装了一个不太漂亮的 API 对象,并添加了一些属于 API 边缘的功能。

class A extends API {
  public A {
    this.APIOption = Option1;
    this.AnotherAPIOption = Option2;
    // a few more
  }

  public ArrayList<String> somethingTheAPIDoesntDo() {
    // Do something the API doesn't provide but I use alot
  }
  // Other shared methods
}

class B extends API {
  public B {
    this.APIOption = Option3;
    this.AnotherAPIOption = Option4;
    // a few more
  }

  public ArrayList<String> somethingTheAPIDoesntDo() {
    // Do something the API doesn't provide but I use alot
  }
  // Other shared methods
}

将两者之间的公共代码推送到抽象基类,并且让子类仅使用专门的选项设置实现其构造函数是否有意义? 这在纸面上是有道理的,但有些感觉很奇怪/违反直觉。我在这里缺少模式吗?

可能的 DRYer 解决方案

class A extends BetterAPIBase {
  public A {
    this.APIOption = Option1;
    this.AnotherAPIOption = Option2;
    // a few more
  }
}

class B extends BetterAPIBase {
  public B {
    this.APIOption = Option3;
    this.AnotherAPIOption = Option4;
    // a few more
  }
}    

abstract class BetterAPIBase extends API {
  public Better APIBase() {}
  public ArrayList<String> somethingTheAPIDoesntDo() {
    // Do something the API doesn't provide but I use alot
  }
  // Other methods
}

编辑

静态工厂模式很好,但我想我也可以添加一个包含我添加的常用方法的接口。

我将使 BetterAPI 类也实现 IBetterAPI,这只会公开我在将实例类型声明为 IBetterAPI 时添加的方法。

interface IBetterAPI{
      public ArrayList<String> somethingTheAPIDoesntDo();
      // other methods I added in BetterAPI
}

//somewhere else:
IBetterAPI niceApi = BetterAPI.createWithOptionSetA();
niceApi.somethingTheAPIDoesntDo();

// Can't do this, nice and hidden.
niceApi.somethingBaseAPIDoes(string uglyOptions, bool adNauseum); 

So I did some refactoring and two of my classes now look exactly the same except for their constructors.

The classes wrap an API object that isn't very pretty, and add some functionality that belong at the edge of the API.

class A extends API {
  public A {
    this.APIOption = Option1;
    this.AnotherAPIOption = Option2;
    // a few more
  }

  public ArrayList<String> somethingTheAPIDoesntDo() {
    // Do something the API doesn't provide but I use alot
  }
  // Other shared methods
}

class B extends API {
  public B {
    this.APIOption = Option3;
    this.AnotherAPIOption = Option4;
    // a few more
  }

  public ArrayList<String> somethingTheAPIDoesntDo() {
    // Do something the API doesn't provide but I use alot
  }
  // Other shared methods
}

Does it make sense to push the common code between the two to an Abstract Base class, and have the subclasses only implement their constructors with the specialized option settings?
It makes sense on paper, but something feels weird/counterintuitive about it. Am I missing a pattern here?

Possible DRYer Solution

class A extends BetterAPIBase {
  public A {
    this.APIOption = Option1;
    this.AnotherAPIOption = Option2;
    // a few more
  }
}

class B extends BetterAPIBase {
  public B {
    this.APIOption = Option3;
    this.AnotherAPIOption = Option4;
    // a few more
  }
}    

abstract class BetterAPIBase extends API {
  public Better APIBase() {}
  public ArrayList<String> somethingTheAPIDoesntDo() {
    // Do something the API doesn't provide but I use alot
  }
  // Other methods
}

EDIT

Static Factory Pattern is nice, but I think I may also add an Interface that includes the common methods I added.

I would make the BetterAPI class also implement IBetterAPI, which would only expose the methods I added wherever I declare the instance's type as IBetterAPI.

interface IBetterAPI{
      public ArrayList<String> somethingTheAPIDoesntDo();
      // other methods I added in BetterAPI
}

//somewhere else:
IBetterAPI niceApi = BetterAPI.createWithOptionSetA();
niceApi.somethingTheAPIDoesntDo();

// Can't do this, nice and hidden.
niceApi.somethingBaseAPIDoes(string uglyOptions, bool adNauseum); 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

林空鹿饮溪 2024-09-16 00:28:31

拥有一个带有参数化(可能是私有)构造函数和多个静态工厂方法的类不是更简单吗?

class BetterAPI extends API {
  private BetterAPI(APIOption option, AnotherAPIOption anotherOption) {
    this.APIOption = option;
    this.AnotherAPIOption = anotherOption;
  }

  public static BetterAPI createWithOptionSetA() {
    return new BetterAPI(Option1, Option2);
  }

  public static BetterAPI createWithOptionSetB() {
    return new BetterAPI(Option3, Option4);
  }

  // ...
}

您问题的核心似乎是在同一个类中不能有多个无参数构造函数。静态工厂方法为此提供了一个很好的解决方案。

Wouldn't it be simpler to have one class with a parametrized (possibly private) constructor and multiple static factory methods?

class BetterAPI extends API {
  private BetterAPI(APIOption option, AnotherAPIOption anotherOption) {
    this.APIOption = option;
    this.AnotherAPIOption = anotherOption;
  }

  public static BetterAPI createWithOptionSetA() {
    return new BetterAPI(Option1, Option2);
  }

  public static BetterAPI createWithOptionSetB() {
    return new BetterAPI(Option3, Option4);
  }

  // ...
}

The core of your problem seems to be that you can't have multiple parameterless constructors in the same class. Static factory methods offer a nice solution to this.

哭了丶谁疼 2024-09-16 00:28:31

这与我要做的非常接近。尽管如果“再少一些”会在构造函数中产生大量冗余代码,我会写:

abstract class BetterAPIBase extends API { 
  public BetterAPIBase(String APIOption, int AnotherAPIOption, ... more ...) {
    this.APIOption=APIOption;
    this.AnotherAPIOption=AnotherAPIOption;
    // a few more
  } 
  public ArrayList<String> somethingTheAPIDoesntDo() { 
    // Do something the API doesn't provide but I use alot 
  } 
  // Other methods 
} 

class A extends BetterAPIBase { 
  public A { 
    super(Option1, Option2, ... more ...);
  } 
} 

class B extends BetterAPIBase { 
  public B { 
    super(Option3, Option4, ... more ...);
  } 
}     

当然,如果任何选项值相同,则不需要传递它们,这就是真正的冗余消除的地方会来的。

That's pretty close to what I'd do. Though if the "few more" makes for a lot of redundant code in the constructor, I'd write:

abstract class BetterAPIBase extends API { 
  public BetterAPIBase(String APIOption, int AnotherAPIOption, ... more ...) {
    this.APIOption=APIOption;
    this.AnotherAPIOption=AnotherAPIOption;
    // a few more
  } 
  public ArrayList<String> somethingTheAPIDoesntDo() { 
    // Do something the API doesn't provide but I use alot 
  } 
  // Other methods 
} 

class A extends BetterAPIBase { 
  public A { 
    super(Option1, Option2, ... more ...);
  } 
} 

class B extends BetterAPIBase { 
  public B { 
    super(Option3, Option4, ... more ...);
  } 
}     

Of course if any of the option values are the same then they wouldn't need to be passed, which is where real redundancy elimination would come.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文