静态工厂:Java设计问题
我有一个基本接口,它定义了一些常见的功能。现在这个基本接口可以由50多个类实现,每个类都有一些不同的附加方法。我想要一个静态工厂,它将根据传递给静态工厂方法的参数返回50个类中任意一个的实例静态工厂: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
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
我想返回classsecondclass
等等。
有这么多条件是不可行的
不行
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)