静态工厂:Java设计问题

静态工厂:Java设计问题,java,design-patterns,static,factory-pattern,Java,Design Patterns,Static,Factory Pattern,我有一个基本接口,它定义了一些常见的功能。现在这个基本接口可以由50多个类实现,每个类都有一些不同的附加方法。我想要一个静态工厂,它将根据传递给静态工厂方法的参数返回50个类中任意一个的实例 public interface Base { public void a(); public void b(); } public class myclass implements Base { // a and b implementation publi

我有一个基本接口,它定义了一些常见的功能。现在这个基本接口可以由50多个类实现,每个类都有一些不同的附加方法。我想要一个静态工厂,它将根据传递给静态工厂方法的参数返回50个类中任意一个的实例

public interface Base {
     public void a();
     public void b();
}

public class myclass implements Base {
     //   a and b implementation

     public String c() {
     }
     public String d() {
     }
}

public class secondclass implements Base {
     //   a and b implementation

     public String e() {
     }
     public String f() {
     }
}
如何实现静态工厂方法。我不确定退货类型

  public synchronized static {return type} getInstance(String arg0) {
         // do something and return any one class based on arg0
  }
编辑: 情景

如果传递的参数是300 我想返回类的对象
myclass

如果参数为900 我想返回class
secondclass

等等。 有这么多条件是不可行的

不行

public synchronized static {return type} getInstance(String arg0) {
   // do something and return any one class based on arg0
   if(arg0.equals("300")) {
       return new myclass();

   }

}
原因: 这是卖不出去的。我正在开发一个公共API,类列表可能会增加到100或500。 我希望我的问题现在更清楚了

更新: 这里强调了非常有用的要点,这就是我的想法

public abstract class Base {

      public abstract void a();
      public abstract void b();

      public synchronized staticabstract Base getInstance(String arg0);

}


public class myclass extends Base {

     private myclass() {}    // private constructor not publicly instantiate 
     // a and b implementation

     public void c();
     public void d();

     @Override
     public synchronized static abstract Base getInstance(String arg0) {
           if(arg0.equalsIgnoreCase("300")) {      // only 1 if condition
                return new myclass();
           }
     }
}



public class secondclass extends Base {

     private secondclass() {}    // private constructor not publicly instantiate 
     // a and b implementation

     public void e();
     public void f();

     @Override
     public synchronized static abstract Base getInstance(String arg0) {
           if(arg0.equalsIgnoreCase("900")) {      // only 1 if condition
                return new secondclass();
           }
     }
}



Client side:
one applicaiton
Base b=Base.getInstance(300);
if(b instanceof myclass) {

}

second application

Base b=Base.getInstance(900);
if(b instanceof secondclass) {

}

返回类型将是接口

例如:

public synchronized static Base getInstance(String arg0) {
    if(arg0.equals("myClass"))
        return new myClass();
    else if (arg0.equals("secondClass"))
        return new secondClass();
}
您可以这样调用具体方法:

Base instance = getInstance("myClass");
((myClass) instance).c();
您也可以直接对其进行强制转换:

myClass instance = (myClass) getInstance("myClass");
instance.c();

更好的方法是泛化静态方法:

static <T extends Base> T create(Class<T> type){
  // create concrete instance of type T and return it
}
编辑2:总结一下讨论,如果工厂无法采用类型或逻辑来创建对象,则唯一的选项是以下选项:

static Base create(String someParameter){
  // create the concrete class and return it
}
客户端代码如下所示:

Base b = create("myArgument");
if(b instanceof SomeDerived){
  SomeDerived d = (SomeDerived) b;
  // use d
} else if(b instanceof OtherDerived){
  // you get the idea
}

不理想,但如果没有
类的实例,就无法泛化
创建
方法使用静态工厂胜过构造函数的相关原因之一(引用自):

静态工厂方法的第三个优点是 构造函数,它们可以返回其返回的任何子类型的对象 类型

因此,从本质上讲,它可以让你写出以下内容:

Base x = Factory.getInstance(TypeX.class); 
x.methodOfBase();
其中,
TypeX
可以完全隐藏并具有私有构造函数

您可能想看看java .UTL.Cuffys/Cuth.API实现,例如考虑静态工厂方法:

public static <T> List<T> synchronizedList(List<T> list)
公共静态列表同步列表(列表列表)
正如您所看到的,返回类型是一个接口,因此返回的对象(列表的一些隐藏实现)只能用作列表

因此,如果您想使用子类型
TypeX
专用的、不属于
Base
接口的
x1()
x2()
方法,您无论如何都必须将对象强制转换为
TypeX

在这种情况下,您可以通过构造函数直接实例化
TypeX
(将其公开),因为静态工厂不会给您任何东西



您可能还想看看本书中使用
静态工厂
而不是
构造函数
的其他3个原因,并验证它们中没有一个适用于您在问题中描述的内容。

那么我如何在运行时访问方法c d e ftime@user3172529请参阅我的编辑。您需要将其转换为具体的类型。将arg0与类名进行比较不是一个合适的解决方案,在这种情况下,我必须编写50个条件,将来如果类增加超过condiitons@user3172529我以为getInstance在接口中。这并不重要。你应该真正遵循普通的java约定,使用大写字母作为你的类名。@Steinar:没错,特别是当他/她谈论实现某些设计模式时。@BheshGurung应该理解,如果我使用的是静态工厂方法,并且过于同步,我是在工厂模式和单例类的上下文中谈论的。@Steinar我的错误键入我严格使用了If-else模式的java-guide-for-namingAn选项使用从字符串到实现的映射。但是,这仅适用于实现为无状态的情况。如果不是,则每次都需要创建一个新实例,可以通过反射或显式使用“new…”。由于在factory方法中根据传递的字符串来确定Base的子类,这不会有帮助,因为调用方不知道他们将获得的类型,“在前面。@Vikdor假设字符串以某种方式表示他们要返回的类型。完全正确。如果无论如何都要传递参数,那么最好传递
,并获得所需的所有类型安全信息。@user3172529:我认为您试图混合使用静态工厂方法和工厂方法。@user3172529:如果您需要调用接口中未定义的方法,而不使用显式强制转换,那么实现这一点的唯一方法就是使用泛型。我更新了我的答案。如果要使用静态工厂,则必须返回接口类型。因此,要么将所有方法a、b、c、…z的集合添加到基本接口并拥有工厂,否则只需使用它们的构造函数实例化自定义类,因为您将强制转换到它们的返回类型以使用它们。使用静态工厂方法的完整点是子类拥有一个私有构造函数。我不希望它们被公开实例化,因为这些对象非常消耗资源。@user3172529要正确使用静态工厂,您需要两个条件:1。通过接口使用子类型。2.使它们直接不可实例化(私有构造函数)。有关更多详细信息,请参阅
effectivejava
。您只支持条件2,但需要1。也只需按照我在上一篇评论中的建议扩展您的
基础
,查看我的上次更新。我希望这会有意义。对不起,但我认为这没有意义。扩展
Base
的意思是让接口Base声明所有可能的子类中的所有方法a~z()。如果某个类
Secondclass
只想实现a、b、e、f,那么它可以将其他方法的实现留空{},或者将
Base
设为抽象类,并为所有方法提供默认实现
public static <T> List<T> synchronizedList(List<T> list)