我在一次采访中遇到了一个问题,我吃了两种食物,比如面包和蛋糕,得到了以下答案:
public class FoodFactory{};
public class Food{};
public static void main(String[] args) {
Food foo = FoodFactory.get("bread");
System.out.println(foo.getClass().getName());
}
考虑到FoodFactory
类和Food
类,我不知道如何使其工作,以便它打印出该类的"bread"
。让它打印面包的唯一方法似乎是创建一个Bread
类,并让FoodFactory
返回它。
我只是想知道我是否遗漏了什么,因为FoodFactory
和Food
是给定的类,所以我认为这是我只需要更改的两个类。有没有一种方法可以实现给定的两个类,并在只使用这两个类的情况下打印"bread"
?
因此,一种方法是创建一个扩展类Food
的类Bread
,并让FoodFactory.get()
根据传递的字符串返回适当的对象。
class Food {};
class Bread extends Food {};
class FoodFactory {
public static Food get(String type){
switch(type){
case "bread" : return new Bread();
default : return new Food();
}
}
}
另一种方法是使用反射。
除非您在运行时编译一个新类(这是可能的,但在这里不合适),否则如果您想返回Bread
实例,您当然需要添加一个类。
理想情况下,Food
最多应该变成一个接口或抽象类。然后有类Bread
和Cake
实现/扩展Food
。您的FoodFactory
有一个静态方法get
,它将食物作为字符串接受。根据值的不同,您可以实例化并返回一个具体的类,它将在打印类名时为您提供所需的内容。
我认为面试官问的真正问题是你是否理解模式和多态性。正如其中一条评论中所指出的,除非真的有Bread类,否则getClass().getName()
不会返回"Bread"。你本可以做的是建议面试官Food
是基类,在这种情况下应该由Cake
和Bread
类扩展,甚至建议将其更改为抽象类或接口。然后,您可以提出一个简单的工厂类,它将在基类接口后面创建所需的实现"隐藏"。
您的问题基本上是Java工厂设计模式的一个例子。假设你有一个项目,分别是一个具有多个接口和不同类的类层次结构,那么创建任何类的最简单方法是什么?这就是工厂用来处理与类实例创建有关的所有操作的地方。
现在,对于您的情况,最方便的方法是将Class Food
更改为一个接口,例如:
public interface Food {
String getType();
}
现在您需要实现interface Food
的Cake
和Bread
类
public class Cake implements Food{
@Override
public String getType() {
return "Cake";
}
}
public class Bread implements Food{
@Override
public String getType() {
return "Bread";
}
}
现在,您需要定义FoodFactory
类,该类具有一个静态get
方法,该方法根据提供的条件返回一个Food
。
public class FoodFactory {
public static Food get(String classifier){
if(classifier.equals("Cake")) return new Cake();
if(classifier.equals("Bread")) return new Bread();
//no matching Food to create
throw new IllegalArgumentException("The " + classifier + " is not a valid classifier");
}
}
拥有Factory后,您可以将其用于任何创建操作。如果你想从Food实例中打印出Bread
,你可以这样实现:
//food is now an instanceof Bread
Food food = FoodFactory.get("Bread");
System.out.println(food.getType());
它只是打印
Bread
此外:为了确保每个创建都只由FoodFactory
处理,您应该使Food类的每个构造函数protected