Java工厂模式的返回类型



这可能是一个非常基本的问题,有一个非常明显的答案,但我很难弄清楚。

如何知道java工厂模式中涉及的类的方法的返回类型。例如,查看下面的代码。。。方法调用的返回类型是什么以及如何正确地进行强制转换。。。以及如何为类编写javadoc。

我正在尝试编写一个库,然后用户可以将其插入到他们的项目中。。。

我有一个接口

public interface myInterface
{
public Object doA();
public Object doB();
}

混凝土等级如下

public class concerete1 implements myInterface
{
public concerete1() {
}
@override
public Object doA()
{ return new String("Hello"); }
@override
public Object doB()
{ return "hello".getBytes(); }
}

public class concerete1 implements myInterface
{
public concerete2() {
}
@override
public Object doA()
{ return "hello".getBytes(); }
@override
public Object doB()
{ return new String("Hello"); }
}

我的工厂等级如下

public class factory
{
private myInterface mi;
public myInterface actionProducer(String choice)
{
switch(choice)
{
case "a":
mi = new concerete1();
break;
case "b":
mi = new concerete2();
break;
}
return mi;
}
}

我的测试选手等级如下

String result = factory.actionProducer("a").doA();

您不应该显式测试工厂方法返回值的动态类型。静态类型应该告诉你所有你需要知道的。这意味着返回类型应该尽可能具体,以告诉您可以对对象执行什么操作。例如,制作不同实现的映射的工厂方法应该返回Map:

public interface MapFactory {
public Map makeMap();
...
}

无论MapHashMapTreeMap还是ConcurrentSkipListMap,都可以使用Map方法与之交互。如果需要调用ceilingKey,而不是Map方法,则存在设计问题。

在您的情况下,您的工厂方法没有任何意义,因为没有比Object更具体的类型可以返回,并且您不能对Object的API之外的返回值进行任何处理。一个更合理的工厂将返回可以以相同方式交互的对象,而不管对象是如何实现的。

您不应该对真实的工厂产品类型感兴趣。抽象工厂是为分解具有公共接口/抽象超类的对象而构建的。所以,如果你有

public abstract class Animal {
public void eat();
public String foo();
}

和实现者类:

public class Dog extends Animal {
public void eat() {
//stuff here
}
public String foo() {
return "howgh";
}
}
public class Cat extends Animal {
public void eat() {
//stuff here
}
public String foo() {
return "meow";
}
}

你的工厂界面看起来像这样:

public interface AnimalFactory {
public Animal createAnimal();
}

混凝土工厂将是

public class CatFactory implements AnimalFactory {
public Cat createAnimal(){
return new Cat();
}
}

public class DogFactory implements AnimalFactory {
public Dog createAnimal(){
return new Dog();
}
}

因此,您可以创建通用接口产品,而不需要知道它们的真实类:

Animal awesomeAnimal = catFactory.createAnimal();
System.out.println(awesomeAnimal.foo());

输出将是"meow"。这是可能的,因为所有产品都是通用接口的子类(此处为Animal)。

在任何情况下,返回类型都将是Object。我不知道你想转换成什么,但如果它是一个String,那么从字节数组转换成String是不可能的。您将不得不使用String类的构造函数之一("String result=new String(factory.actionProducer("a").doA();")。如果您调用"doB()"(从而将字符串作为对象),您可以通过强制转换它("String result=(String)factory.action生产者("a).docA()")或通过调用返回对象的toString()方法将其转换为字符串("字符串结果=factory.actionProducer("a").doB().toString();").

这些方法的Javadoc会将它们中的每一个描述为返回一个Object,因为它们就是这样做的

简而言之,我会将"doA()"one_answers"doB()"的返回类型更改为它们实际返回的类型(字符串或字节数组),但这可能不是你想要做的事情的选项。一些额外的上下文可能有助于得出更详细的答案。

编辑:对不起,我没有意识到String和字节数组的返回类型在这两个实现中是颠倒的。在答案中,我将"doA()"描述为返回字节数组,将"doB()"定义为返回字符串,我相信这些在您在示例(Concrete1)中使用的实现中会发生变化。然而,其他一切都很重要。

最简单的答案是将"result"声明为Object,然后强制进行强制转换,只希望你做对了:如果你不这样做,你将在运行时得到一个错误:

Object obj = factory.actionProducer("a").doA();
String str = (String) obj;

然而,在您的示例中,doA()返回String或byte[],具体取决于实现的选择,因此对于"b",这将失败,对于"a",这会成功。也许这是问题中的拼写错误?

如果对目标有一个稍微清晰的定义,使用泛型类型可能会有所帮助,但如果没有更多信息,很难说。

最新更新