簡體   English   中英

如何通過反射減少IF-ELSE的使用? 我可以獲取代碼示例

[英]How to reduce the usage of IF - ELSE by reflection ? Can I get the code example

我試圖對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等?

請記住,使用反射來解決問題通常會給您帶來兩個問題-使用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");
}

您可以將concreate披薩的類提供給factory方法-

public static <T extends Pizza> T getConcretePizza(Class<T> clazz) {
    try {
        return clazz.newInstance();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

為了減少“ if-else”的使用率來回答您的問題,您可以動態確定要使用的類,例如,而不是

if (PType.equals("Cheese")) {
    p=new CheesePizza();

你可以用

Class.forName(PType + "Pizza").newInstance(); // might need a package

(以上假設無參數構造函數)

這樣就可以消除任何交換式行為。

但是我不推薦這個 上面的代碼很難調試並且不明顯。 您的IDE可能會將此類標記為未使用,並且可能在將來的重構期間將其標記為刪除。 在絕大多數情況下,我希望澄清。

簡而言之,我寧願通過if / else序列,基於字符串的開關,字符串到方法對象的映射等來指定可用披薩的規格,而不是通過任何復雜的,非顯而易見的,可能是脆弱的機制來指定。

假設您有自己的接口Pizza public interface Pizza { \\*some methods *\\}

以及諸如public class CheesePizza implements Pizza {}

您可以創建枚舉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.

}

PS我注意到您在包裹名稱中使用了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; 


     //....
      }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM