我试图使用反射PizzaFactory类的代码,这样我就可以删除if else条件,使我的代码更动态。但我不知道是怎么回事。
Pizza.java
package PizzaTrail;
import java.util.List;
//this is the main abstract factory which will be extended by the concrete factory
public abstract class Pizza { public abstract List fetchIngredients(String Type); }
PizzaFactory.java
package PizzaTrail;
import java.util.List;
//this is the concrete factory
public class PizzaFactory extends Pizza
{
public static Pizza getConcretePizza(String PType)
{
Pizza p=null;
if (PType.equals("Cheese"))
{
p=new CheesePizza();
} else if (PType.equals("Pepperoni"))
{
p=new PepperoniPizza();
}
else if (PType.equals("Clam"))
{
p = new CalmPizza();
}
else if (PType.equals("Veggie"))
{
p= new VeggiePizza();
}
return(p);
}
}
ChessePizza.java
package PizzaTrail;
import java.util.ArrayList;
import java.util.List;
public class CheesePizza extends Pizza {
List ing = new ArrayList();
@Override
public List fetchIngredients(String Type)
{
ing.add("Ingredient : Shredded Mozzarella Cheese");
ing.add("Ingredient : Peppers");
ing.add("Ingredient : Feta cheese");
ing.add("Ingredient : Pesto");
return (ing);
}
}
}
谁能帮助我得到在pizzaFactory类中使用的反射,以便我可以动态地调用类CheesePizza等?
您可以将concreate pizza的类提供给工厂方法-
public static <T extends Pizza> T getConcretePizza(Class<T> clazz) {
try {
return clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
记住使用反射来解决问题通常会留下两个问题-使用enum
如何?
enum Pizzas {
Cheese {
@Override
Pizza make() {
return new CheesePizza();
}
},
Pepperoni {
@Override
Pizza make() {
return new PepperoniPizza();
}
},
Clam {
@Override
Pizza make() {
return new ClamPizza();
}
},
Veggie {
@Override
Pizza make() {
return new VeggiePizza();
}
};
abstract Pizza make();
public static Pizza make(String type) {
return Pizzas.valueOf(type).make();
}
}
public void test() {
Pizza pizza = Pizzas.make("Cheese");
}
要回答您关于减少'if-else'使用的问题,可以动态地确定要使用的类,例如,而不是
if (PType.equals("Cheese")) {
p=new CheesePizza();
你可以用
Class.forName(PType + "Pizza").newInstance(); // might need a package
(以上假设为无参数构造函数)
,这将删除任何切换类型的行为。
但是我不推荐这个。上述内容难以调试且不明显。您的IDE可能会将这些类标记为未被使用,并在将来的重构中可能被删除。在绝大多数情况下,我赞成清晰。
简而言之,我更愿意通过if/else序列、基于字符串的开关、字符串到方法对象的映射等方式来指定可用披萨的规范,而不是任何复杂的、不明显的、可能脆弱的机制。
假设你有你的界面披萨public interface Pizza { *some methods *}
和public class CheesePizza implements Pizza {}
可以创建enum PizzaType
enum PizzaType {
Cheese(CheesePizza.class);
Class<?> type;
PizzaType(Class<?> type) {
this.type = type;
}
Pizza create() {
try {
return (Pizza) type.newInstance();
} catch (Exception e) {
return null;
}
}
}
现在要创建新的新鲜披萨你所需要做的就是
Pizza pizza = PizzaType.Cheese.create();
您可以维护这样一个映射:
private static final Map<String, Class<? extends Pizza>> PIZZAS;
static {
Map<String, Class<? extends Pizza>> pizzas = new HashMap<String, Class<? extends Pizza>>();
pizzas.put("Cheese", CheesePizza.class);
pizzas.put("Pepperoni", PepperoniPizza.class);
PIZZAS = Collections.unmodifiableMap(pizzas);
}
然后,例如:
public static Pizza getConcretePizza(String type) {
Class<? extends Pizza> clazz = PIZZAS.get(type);
if (clazz == null) {
throw new IllegalStateException("No pizza of type " + type);
}
try {
return clazz.newInstance();
} catch (Exception e) {
throw new IllegalStateException("Unable to instantiate pizza of type " + clazz.getSimpleName(), e);
}
}
您将无法避免使用反射条件,否则您的代码将在某些时候失败。但是,对于您的请求,您可以这样做:
public static Object getConcretePizza(String type) throws Exception{
String pizza = String.format("pizza_trail.%sPizza", type);
Class<?> clazz = Class.forName(pizza);
Object pizzaClass = clazz.newInstance();
return pizzaClass;
}
然后,在实现过程中,您可以使用if条件检查来确定您想要的披萨类型:
Object pizzaObject = PizzaFactory.getConcretePizza("Cheese");
if(pizzaObject instanceof CheesePizza){
CheesePizza pizza = (CheezePizza) pizzaObject;
// call CheesePizza related methods here.
}
注:我注意到你的包装名称中使用了Camelcase。养成在包中使用小写字母的习惯,当涉及多个单词时,使用下划线。这只是Java的约定,虽然不是必需的。
//public static Pizza getConcretePizza(String PType){
public static Pizza getConcretePizza(Class cType){
/**
*
if (PType.equals("Cheese"))
{
p=new CheesePizza();
}//..............
*/
Constructor ctor = cType.getConstructor();
Object object = ctor.newInstance();
p = object;
//....
}