111,098
社区成员




public interface IComm
{
bool IConn(c);
}
public class ComConfig
{
public int p;
public int timeout;
}
public class Com :IComm
{
public bool IConn(ComConfig c)
{
return true;
}
}
public class LanConfig
{
public string ip;
public int port;
}
public class Lan : IComm
{
public bool IConn(LanConfig c)
{
return true;
}
}
public class CommFactory{
public IComm GetComm()
{
//根据配置返回IComm对象
}
public IComm GetComm(CommType type)
{
//根据type返回IComm对象
}
}
连接时需要负责指定其配置么?(是否有对同一个IComm对象转换不同配置的业务场景?)
如果不需要,让每个接口实现类自行loadconfig 好了
如果需要:那么
调用者需要关心配置的细节么?(是否这些配置已经固化下来了?)
如果已经固化了,可以
public interface IComm
{
bool IConn(string configName);
}
public class Com :IComm
{
public bool IConn(string configName)
{
//load Com config by configName
return true;
}
}
public class Lan : IComm
{
public bool IConn(string configName)
{
//load Lan config by configName
return true;
}
}
如果没有固化,调用者可以随意指定config细节并对其执行结果负责,那么抽象成接口的必要性就值得商槯了
总之,你大可找个调用者代码的开发人来讨论,看看两边愿意承担多少责任,抽象的粒度也就出来了
interface IConn
{
void Connect();
}
正因为不能在父类定义所谓差别,而父类又需要有一个 Connect 操作,所以这里不应该纠结什么参数。各个子类扩展中会定义它自己的 this.XXXXX 这样的参数,并非用 Connect 方法参数来实现。
你再好好重温一下上面这些设计概念。interface IConfig
{
void Connect();
}
这样 Comm 实现自己的 Connect 方法,而 Lan 则实现完全不同的 Connect 方法。也就是说,父类的某处具体实现的差别定义在子类,而不是父类。
而你说的所谓父类就实现好一个万能Connect类而仅仅靠“传入的参数类型不同”来做到万能,那是万万不能的,是根本就不符合最基本、很容理解的面向对象继承概念的。
public class CommFactory{
public IComm GetComm(string configName) // or define enum
{
IComm comm;
//Load Comm Type by config name
//select commType, configData form CommConfigTable
if (commType = "com") {
var com = new Com();
//Build com config
com.port = 2;
comm = com;
}
if (commType = "lan"){
var lan = new Lan();
//Build lan config
lan.url = "http://someurl";
comm = lan
}
return comm;
}
}
config name 甚至可以更进一步,使用连接端的名字,比如 谷歌/百度...
那么调用者仅关心需要和谁连接,而不需要关心通过什么类型连接,更不必关心具体什么配置参数
IDevice x = new Comm(2);
或者IDevice x = new Comm();
var y = (Comm)x;
y.Port = 2;
或者var x = new Comm();
x.Port = 2;
(IDevice)x.Port =1;
总之,调用者知道细节。而你的“限定的范围”是说父类(父接口)不是规定父协议,反而是父类要实现所有子类的“限定”,这说明你从根本上就没有理解面向对象能做什么、不能做什么。IDevice x = new Comm();
(Comm)x.Port = 2;
.....
x.设备某方法();
或者写[code=csharp]var x = new Comm();
x.Port = 2;
.....
x.设备某方法();[
直接可以把 x 用在各种针对 IDevice 的多态操作中/code]IDevice x = new lan("tcp://189.1.2.3:8676");
你正好相反,你说写下这段代码的程序员不知道子类细节,而实现(可能是1年前开发出来的) Device 父类却能够知道将来所有扩展子类的细节。public class Lan: IDevice, ILanConnect, ILanConfig
{
public void 设备某方法()
{
.....使用 this.IP 等等来实现 Conn特殊定义
}
}
public class Comm: IDevice, ICommConnect, ICommConfig
{
public void 设备某方法()
{
.....使用 this.Port 等等来实现 Conn特殊定义
}
}
那么你自然可以写IDevice x = new Comm();
x.Port = 2;
.....
x.设备某方法();
你还可以为 Comm 单独定义一个实例化方法来把 Port 等参数封装进去。
关键在于,各个子类独特的特性自然是定义在子类(子接口)上的,为什么纠结到什么父类(父接口)那里去呢?