2016-06-13 130 views
2

例如,我有這個類:如何僅基於基本類型創建派生對象?

public abstract class Device 
{ 
    public Device() 
    { 
    } 

    public Device(XmlDevice xmlDevice) 
    { 
     // creating device by xmlDevice 
    } 
} 

public class Modem : Device 
{ 
    public Modem() 
    { 
    } 

    public Modem(XmlModem modem) 
    { 
     // creating modem by xmlModem 
    } 
} 

public class Plc : Device 
{ 
    public Plc() 
    { 
    } 

    public Plc(XmlPlc plc) 
    { 
     // creating plc by xmlPlc 
    } 
} 


public abstract class XmlDevice 
{ 
    public XmlDevice() 
    { 
    } 
} 

public class XmlModem : XmlDevice 
{ 
    public XmlModem() 
    { 
    } 
} 

public class XmlPlc : XmlDevice 
{ 
    public XmlPlc() 
    { 
    } 
} 

我有XmlDevice對象名單 - 我怎麼能基於其類型創建設備對象?我能做到這一點是這樣的:

foreach(xmlDevice in xmlDevicesList) 
{ 
    if(xmlDevice is XmlModem) 
     devicesList.Add(new Modem((XmlModem)xmlDevice)); 
    else if(xmlDevice is XmlPlc) 
     devicesList.Add(new Plc((XmlPlc)xmlDevice)); 
} 

但我想避免「是」語句和轉換對象。更乾淨的方式來做到這一點?

+2

閱讀關於工廠設計模式 –

+0

好的,但在工廠,我必須使用「是」並施展太多......? – Bero

+0

請看看我幾年前提出的類似問題的回覆:http://stackoverflow.com/questions/15998071/getting-past-open-closed-principle –

回答

4

您對當前實施的反感是有根據的。我可以向你保證,一旦你添加新的設備類型,它就會打破。更糟糕的是,編譯器無法知道您希望實例類型檢查是詳盡無遺的,因此不會通過發出錯誤信號來幫助您。

如果你可以改變Xml*類,你可以簡單地CreateDeviceXmlDevice引入一個抽象方法,並重寫它的派生類:

public abstract class XmlDevice 
{ 
    // ... 
    public abstract Device CreateDevice(); 
    // ... 
} 

public class XmlModem : XmlDevice 
{ 
    // ... 
    public override Device CreateDevice() 
    { 
     return new Modem(this); 
    } 
    // ... 
} 

現在,你可以簡單地這樣做:

devicesList = xmlDevicesList.ConvertAll(x => x.CreateDevice()); 

也許這種方法的最大好處是編譯器不會讓你在創建一個新的設備類型的時候沒有實現CreateDevice方法。

+0

謝謝,這是如此簡單...如果我想傳遞一些不同的參數(Modem和Plc不同)給構造函數,那麼工廠將是必要的? – Bero

+0

什麼參數,例如? –

+0

其他一些物體。例如:調制解調器的Antena和PLC的OutputModule – Bero

相關問題