简体   繁体   English

在工厂方法中避免instanceof

[英]Avoiding instanceof in factory method

I'm looking for an improved solution to the following problem. 我正在寻找以下问题的改进解决方案。 I have an object, which is passed to a factory; 我有一个对象,该对象已传递给工厂。 the factory will inspect the object type, create another type, which it populates with data from the incoming object, and returns the new one. 工厂将检查对象类型,创建另一个类型,并使用传入对象中的数据填充该类型,然后返回新的类型。

...

public MyAbstractClass create(MyObject a) {

    if (a instanceof A) {
        A obj = (A) a;
        return new MyAbstractClass_1 (obj.getField(), factoryField);
    } 
    else if (a instanceof B) {
        B obj = (B) a;
        return new  MyAbstractClass_2 (obj.getSomething(), obj.getSomethingElse(), factoryField);
    } 

}

Instances of the return type are treated generically afterwords. 返回类型的实例通常被视为后缀。 Going forward I need to support more types and if possible I'd like to avoid an instanceof solution. 展望未来,我需要支持更多类型,如果可能的话,我希望避免使用instanceof解决方案。 How can I improve this? 我该如何改善?

Can you add the create method to MyObject instead? 您可以将create方法添加到MyObject吗? That way you won't need instance of anymore because each instance of MyObject knows how to 'create'. 这样,您将不再需要实例,因为MyObject的每个实例都知道如何“创建”。 You won't have a factory anymore though :( 你不会再有工厂了:(

It would look something like (assuming MyObject is an interface. if it's a class, then just extend instead): 它看起来像(假设MyObject是一个接口。如果它是一个类,则直接扩展):

interface MyObject {
  ...
  public MyAbstractClass create(MyObject a);
  ...
}

public class A implements MyObject {
  ...
  public MyAbstractClass create(MyObject a) {
    return new MyAbstractClass_1 (obj.getField(), factoryField);
  }
  ...
}

public class B implements MyObject {
  ...
  public MyAbstractClass create(MyObject a) {
    return new MyAbstractClass_2 (
      obj.getSomething(),
      obj.getSomethingElse(),
      factoryField);
  }
  ...
}

The bodies of your if statements should be virtual or abstract members on MyObject . if语句的主体应该是MyObject上的虚拟或抽象成员。

abstract class MyObject {
   public abstract MyAbstractClass create();
}

class A extends MyObject {
   @Override
   public MyAbstractClass create(Object factoryField) {
      return new MyAbstractClass_1 (this.getField(), factoryField);
   }
}

class B extends MyObject {
   @Override
   public MyAbstractClass create(Object factoryField) {
      return new  MyAbstractClass_2 (this.getSomething(), this.getSomethingElse(), factoryField);
   }
}

Generally, when you see yourself checking the type of an object to do something different depending on the concrete type, that likely means that you should be using polymorphism and the code should be going into the concrete types themselves. 通常,当您看到自己检查对象的类型以根据具体类型进行不同的操作时,这可能意味着您应使用多态性,并且代码应直接进入具体类型。

Updated that the MyObject data should be coming from the current instance and not passed as a parameter, as you pointed out. 如您所指出的那样,更新了MyObject数据应来自当前实例,而不应作为参数传递。 Only issue is that I'm not sure where you'd put factoryField now. 唯一的问题是我不确定您现在将factoryField放在factoryField You could pass it as a parameter as above, and since these are virtual members you could still have a factory as well: 您可以像上面一样将其作为参数传递,由于这些是虚拟成员,因此您仍然可以拥有一个工厂:

class SomeFactory {
   private Object factoryField;

   public SomeFactory(Object factoryField) {
      this.factoryField = factoryField;
   }

   public MyAbstractClass create(MyObject a) {
      return a.create(factoryField);
   }
}

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

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