简体   繁体   English

如何在限制性上下文中实现工厂模式?

[英]How to implement a factory pattern in a restrictive context?

I have a class, let's say A , that extends B . 我有一个类,比如说A ,它extends B I cannot change neither the name of the class, nor what extends. 我既不能更改类的名称,也不能更改其范围。

However, there is a method in A , let's say doSomething (which I cannot rename). 但是, A有一个方法,比如说doSomething (我无法重命名)。

According to a flag, sent in the constructor of A I can do something or something else. 根据发送给A的构造函数的标志,我可以做某事或其他事情。

How do you suggest to handle the fork in doSomething according to the flag, given all these restrictions? 考虑到所有这些限制,您如何建议根据标志处理doSomething中的fork?

Thanks 谢谢

Without further information: 没有更多信息:

public Foo doSomething() {
   if( flag ) {
       return super.doSomething();
   } else {
       return doSomethingElse();
   }
}

You could use the strategy pattern but it would add dozens of lines of code with little benefit other than the feeling you applied a design pattern. 您可以使用策略模式,但是它会添加数十行代码,除了您应用了设计模式之外,几乎没有什么好处。

With the necessary indirection in method calls, if might even be slower. 在方法调用中使用必要的间接调用,甚至可能更慢。

You can choose one of 2 options in my opinion: 您认为我可以选择2个选项之一:

  • Use the flag and for doSomething into 2 inner methods according to the flag. 使用该标志,并根据该标志将doSomething分为2种内部方法。 For example: 例如:

     public class A extends B { private boolean forkFlag; public A (boolean forkFlag) { this.forkFlag = forkFlag; } public void doSomething() { if (forkFlag) { doSomething1(); } else { doSomething2(); } } private void doSomething1() { ... } private void doSomething2() { ... } } 
  • Create a strategy implementation: 创建策略实施:

     public class A extends B { private boolean forkFlag; private Runnable doSomethingImpl; public A (boolean forkFlag) { if(forkFlag) { doSomethingImpl = new DoSomethingImpl1(); } else { doSomethingImpl = new DoSomethingImpl2(); } } public void doSomething() { doSomethingImpl.run(); } } public class DoSomethingImpl1 implements Runnable { public void run() { ... } } public class DoSomethingImpl2 implements Runnable { public void run() { ... } } 

Deciding between those 2 depends on your needs. 在这2个之间进行选择取决于您的需求。 If this fork is something minor, just a use case in a regular flow, I'd go with the first option. 如果这个分叉很小,只是常规流程中的一个用例,我会选择第一个选项。 If there's a chance that you might need to have a third flow I'd go with the strategy pattern and enjoy the decoupling it provides. 如果有可能您需要进行第三次流程,我将采用该策略模式并享受其提供的解耦功能。

With strategy you'll be able to inject the implementation you want from outside the class and be totally unaware of the implementation of doSomething just by changing the constructor: 使用策略,您将能够从类外部注入所需的实现,而仅通过更改构造函数就完全不知道doSomething的实现:

public A (Runnable doSomething) {
   this.doSomething = doSomething;
}

The injection pattern is probably the most elegant and will create a complete decoupling of your code from the implementation. 注入模式可能是最优雅的,它将创建代码与实现的完全解耦。 Also, you might change the implements Runnable into a more specific interface of your own public interface DoSomething to make it more robust. 另外,您可以将implements Runnable更改为您自己的public interface DoSomething一个更特定的接口,以使其更强大。

you have to use Strategy pattern here 你必须在这里使用Strategy模式

public A(boolean flag){
    if(flag == true){
        this.service = new DoSomethingStrategy();
    }else{
        this.service = new DoSomethingElseStrategy();
    }
}

if your code grows, logically, better use a Factory on constructor: 如果逻辑上代码增长,最好在构造函数上使用Factory:

public A(boolean flag){
    this.service = DoSomethingFactory.getService(flag);
}

and copy the code inside the DoSomethingFactory ; 然后将代码复制到DoSomethingFactory内部;

and finally on your doSomething method 最后是你的doSomething方法

public void doSomething(){
    this.service.doSomething();
}

and your behaviour for doSomething is encapsulated into a strategy structure. 并且您将doSomething的行为封装到策略结构中。

Why can't you create another class C that also extends B and use it instead of A as necessary? 为什么不能创建另一个扩展了B的类C并根据需要使用它代替A? It's usually better to avoid conditionals and hard-coding the construction of strategies inside a class, if you can. 如果可能的话,通常最好避免使用条件,并在类中对策略的构造进行硬编码。

You don't need to touch the base class, just extend it with another implementation. 您不需要接触基类,只需将其扩展为另一个实现即可。

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

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