如何通过反射减少IF - ELSE的使用?我可以得到的代码示例



我试图使用反射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; 

     //....
      }

相关内容

  • 没有找到相关文章

最新更新