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

相关问题