亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

有沒有比使用反射在繼承層次結構中通過工廠方法實例化元素更好的方法?

有沒有比使用反射在繼承層次結構中通過工廠方法實例化元素更好的方法?

一只名叫tom的貓 2023-03-02 10:06:42
我構建了一個繼承層次結構,其中一堆具體類繼承自抽象超類A。A具有一個強制屬性 Stringa和一個可選的 Mapb和 xml 模型規范的模型元素。和a中可能的鍵值對b都是 jaxp.NamedNodeList 的一部分。a因此,要設置和 的值,b我總是需要遍歷列表并檢查當前屬性是否具有名稱“id”,并分別設置 的值a或將鍵值對添加到b. 顯然有人想將其外包給工廠方法等。但是,在抽象超類中實現靜態工廠方法A顯然是不夠的,因為通過返回 A 的新實例,我需要在使用工廠方法創建它時將實例化向下轉換為具體元素。所以我想出了一個使用反射的解決方案,但我真的很不安全,因為沒有更簡單的方法來解決一個看起來如此普遍的問題。有沒有更簡單的解決方案?這是我的工廠模式,ClassCastException當將 A 向下轉換為 B 時,會產生這樣的結果SubclassB b = (SubclassB) AbstractSuperClassA.createWith(attributes);:public static AbstractSuperClassA createWith(NamedNodeMap attributes) {    Map<String, String> attributeMap = new HashMap<>();    String a= null;    for (int i = 0; i < attributes.getLength(); i++) {        if (attributes.item(i).getNodeName().equals("id")) {            a = attributes.item(i).getNodeValue();        }        attributeMap.put(attributes.item(i).getNodeName(), attributes.item(i).getNodeValue());    }    if (a == null) {        // throw RuntimeException    }    return new AbstractSuperClassA (identifier, attributeMap);}這是通用的反射實現:public static <T extends AbstractSuperClassA > T init(NamedNodeMap attributes, Class<T> clazz) {    Map<String, String> attributeMap = new HashMap<>();    String a= null;    for (int i = 0; i < attributes.getLength(); i++) {        if (attributes.item(i).getNodeName().equals("id")) {            a = attributes.item(i).getNodeValue();        }        attributeMap.put(attributes.item(i).getNodeName(), attributes.item(i).getNodeValue());    }    if (a== null) {        // throw RuntimeException    }    try {        Constructor<T> constructor = clazz.getConstructor(String.class);        T newElement = constructor.newInstance(a);        newElement.setAttributes(attributeMap);        return newElement;    } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {        log.error(e.getMessage(), e);    }    return null;}
查看完整描述

1 回答

?
藍山帝景

TA貢獻1843條經驗 獲得超7個贊

您的init方法似乎需要一種方法來基于單個值創建給定類的實例。String


在這種情況下,您不需要反思。無需傳入Class實例化和初始化,您可以實現一種“策略模式”形式,其中策略是可變的并且僅定義如何創建新的、ID 初始化的對象。


在 Java 8 及更高版本中,您可以為此使用函數式接口和 Lambdas:


private <T extends AbstractSuperClassA > T init(NamedNodeMap attributes, Function<String,T> creator) {

  ...

  T newElement = creator.apply(identifier);

  ...

}

然后適當地使用它,例如


B someB = init(attrs, B::new);

C someC = init(attrs, id -> {C c = new C(); c.setId(id); return c;});

...

然而,問題是您如何決定應該實例化哪個具體類。在任何情況下,該邏輯都必須在某個地方進行編碼,因此可能有更好的方法來連接邏輯以收集值和初始化新實例的邏輯。


是否要求實例id在構造函數中接收?還是可以稍后設置?


查看完整回答
反對 回復 2023-03-02
  • 1 回答
  • 0 關注
  • 106 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號