请问,这种情况如何处理?

byteman_daydayup 2007-03-05 10:20:18
当从一个接口,继承出了多个子类,接口规范了子类的外部行为,然后某个子类却因为某种原因需要扩展其接口,这种情况该如何处理?? 是修改它们共有的父类接口,还是通过装饰模式来为需要扩展接口的子类增加接口(但是装饰模式,好象只能增强或修改某个接口,不能扩展出新的接口).如果装饰模式不行的话,通过修改父接口,必然为其他子类增加上不必要的接口.这种情况下我又想针对接口编程,该怎么办啦??
...全文
400 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
UltraBejing 2008-05-01
  • 打赏
  • 举报
回复
以后需再关注,现在先帮你顶一下
knowledge_Is_Life 2008-05-01
  • 打赏
  • 举报
回复
支持搂主,收藏
wanglovec 2007-03-24
  • 打赏
  • 举报
回复
这是个问题
lyg_zy 2007-03-24
  • 打赏
  • 举报
回复
sorry,上边写的东西有些错误,现在再写一遍:

enum eType
{
eBase,
eDeriv1,
eDeriv2,
}
class IBase
{
public:
virtual void func1() = 0;
virtual void func2() = 0;
virtual void* QueryInterface(eType nType) = 0;

};

class BaseImpl:public IBase
{
public:
void func1();
void func2();
void* QueryInterface(eType nType)
{
if (nType==eBase)
{
return (IBase *) this;
}
return NULL;
};
};
如果第一个子类接口如下:
class IDerive1:
{
public:
virtual void func3() = 0;
}
class DeriveImp1 :public BaseImpl,public IDerive1
{
public:
//void func1(); 这个可以不实现了,BaseImpl已实现
//void func2();这个可以不实现了,BaseImpl已实现
void func3(); //IDerive1接口
void* QueryInterface(eType nType)//重载此虚函数
{
if (nType==eDevive1)
{
return (IDerive1 *) this;
}
return NULL;
}

};

然后使用的时候这样使用
IBase *pBase= new DeriveImp1();
pBase->func1();
IDerive1* pDerive1=(IDerive1*)pBase->QueryInterface(eDerive1);
if(pDerive1)
{
pDerive1->func3();
}

以上代码用一enum来标识不同的派生接口。我们在得到任一基类接口对象后,都可以用enum类型来探查他实际支持的派生类接口从而确定我们实际的调用。可以通过不停的扩充enum和派生类接口来完成扩展。
lyg_zy 2007-03-24
  • 打赏
  • 举报
回复
enum eType
{
eBase,
eB,
eC,
}
class IBase
{
public:
virtual void func1() = 0;
virtual void func2() = 0;
virtual void* QueryInterface(eType nType) = 0;

};

class BaseImpl:public IBase
{
public:
void func1();
void func2();
virtual void* QueryInterface(eType nType)
{
if (nType==eBase)
{
return (IBase *) this;
}
return NULL;
};
};
如果子类B正是我要扩展的
class IB:
{
public:
virtual void func3() = 0;
}
class B:public BaseImpl,public IB
{
public:
void func1();
void func2();
void func3(); //扩展了的接口
virtual void* QueryInterface(eType nType)
{
if (nType==eB)
{
return (IB *) this;
}
return NULL;
}

};

然后使用的时候这样使用
IBase *p= new B();
p->func1();
IB* pB=p->QueryInterface( 1);
if(pB)
{
pB->func3();
}
lyg_zy 2007-03-24
  • 打赏
  • 举报
回复
这个问题一种优雅的方式可以采用COM里的方式.所以的创建都可以返回一基类接口(比如Com里的IUnknow)接口。这样可以调用基类的所有方法,然后每个接口都一QueryInterface(int nType)
(在Com里int nType是一GUID)查询返回它的子类接口不就行了吗?看看Com里的实现手法吧。


iambic 2007-03-06
  • 打赏
  • 举报
回复
Adaptor
heguodong 2007-03-06
  • 打赏
  • 举报
回复
但是装饰模式,好象只能增强或修改某个接口,不能扩展出新的接口
概念上错误
装饰模式的意图是为了不该边原有接口的前提下扩展接口
注意前提只是不改变原有接口

class ICar
{
public:
virtual void Run() = 0;
};
class ColorCar:public ICar
{
ICar car;

public :

ColorCar(ICar _car)
{
car=_car;
}

virtual color GetColor(){return null;}
virtual void Run(){}
}
ytfhwfnh 2007-03-05
  • 打赏
  • 举报
回复
最好的办法是在IBase中添加一个退化了的方法:
class IBase
{
public:
virtual void func1() = 0;
virtual void func2() = 0;
virtual void func3() { };
};

这样,以后子类中需要func3()的时候也方便扩展。如果没有func3()的子类,通过基类指针使用了func3(),你希望怎么处理?可以添加到IBase中。
byteman_daydayup 2007-03-05
  • 打赏
  • 举报
回复
请问你是说这样吗?
class IBase
{
public:
virtual void func1() = 0;
virtual void func2() = 0;
};

class A:public IBase
{
public:
void func1();
void func2();
};
如果子类B正是我要扩展的
class IB:
{
public:
virtual void func3() = 0;
}
class B:public IBase,public IB
{
public:
void func1();
void func2();
void func3(); //扩展了的接口
};

然后使用的时候这样使用
IB *p = new B();
p->func3(); //这样使用的也是IB这个接口,也算是针对接口编程了吧??
我理解的对吗??
byteman_daydayup 2007-03-05
  • 打赏
  • 举报
回复
如果我直接扩展了子类的接口,那么如果我使用的是它们父类的接口的话,就不能使用到扩展后的子类的接口啊
比如
class IBase
{
public:
virtual void func1() = 0;
virtual void func2() = 0;
};

class A:public IBase
{
public:
void func1();
void func2();
};
如果子类B正是我要扩展的
class B:public IBase
{
public:
void func1();
void func2();
void func3(); //扩展了的接口
};
这样我在使用子类B的时候
IBase* p =new B();
p->func3(); //这样就访问不了func3.
但是如果这样
B* b = new B();
b->func3() //这样就依赖于了具体的类B了,不是针对接口编程了.
这种情况有什么好的方法吗??

ytfhwfnh 2007-03-05
  • 打赏
  • 举报
回复
直接扩展子类的接口不行吗?不知道子类的具体要求是什么?最好能举具体的例子。
byteman_daydayup 2007-03-05
  • 打赏
  • 举报
回复
我是这样采用观察者模式的,首先网络通讯类继承通讯类和被观察者类这2个接口,然后界面类继承观察者类,当网络通讯类检测到新的客户加入或者断开的时候,会更新在先客户断链表中的类容,然后调用观察者的notify方法来通知他,让界面类根据我更新后的在线客户链表中的内容来更新界面,然后用户可能会选择某几个在线的客户,然后给他们发送相同的命令,当选中某几个时候,会调用被观察者提供的更新待发送客户端链表内容的方法,来修改待发送链表中的客户,当使用writerbuffer时候,会根据实际待发送客户断链表中的客户来发送数据给它们!
byteman_daydayup 2007-03-05
  • 打赏
  • 举报
回复
我现在的做法是这样的,因为是才用模式,很多东西觉得生搬硬套的感觉

因为网络通讯类在接收到新的客户端加入的时候,需要通知界面显示新到的客户,以便选择,所以我采用了观察者模式.
在网络通讯类中聚合1个管理在线客户SOCKET和1个管理选中待发送客户端SOCKET的链表,一个用来接收上线的客户,以便显示到界面上,一个管理那些将要被发送命令的SOCKET,待我调用接口中的writebuffer命令的时候,就查询第2个连表中的socket,一个一个的通过他们发送数据.
byteman_daydayup 2007-03-05
  • 打赏
  • 举报
回复
我这里遇到这样一个实际问题:
需要设计一个程序,能够通过网络方式或者串行口方式发送命令去控制下位机,下位机大概有100多台,分布在各地.其中网络方式只需要实现一个C/S模式的S端,因为下位机的各个控制器会主动连接到一个固定的IP上来,等到下位机连接上我的服务器以后,我可以选择一个或多个指定的客户端下位机.向他们一起发送我的控制命令.串口方式是本地配置下位机,只能一台一台的发命令给下位机,网络方式要求是远程并且可以多台一起设置.

我抽象出了这么一个公共的接口
class TCommunication
{
public:
virtual UINT32 WriteBuffer(UINT8* buffer, UINT32 len) = 0;
virtual UINT32 ReadBuffer (UINT8* buffer, UINT32 len) = 0;
virtual ~TCommunication(){};
virtual int Setting(UINT32 speed, UINT16 port) = 0;
virtual int Start() = 0;
virtual int Stop() = 0;

};
然后分别实现串口类和网络类(继承通讯接口).但是他们两个子类之间又有一些不同之处

串口方式很简单,就只需要同时给一台机器发命令就好了
网络方式需要给多台一起发命令,因此它内部需要一个容器来保存各个客户端的SOCKET.然后循环发送命令,并且还需要设计一个界面来显示当前上线的客户端,然后根据你的选择一个或多个,给指定的客户发数据.
所以感觉两个子类应该可以从通讯借口中继承下来.
foochow 2007-03-05
  • 打赏
  • 举报
回复
class IBase
{
public:
virtual void func1() = 0;
virtual void func2() = 0;
};
class b :public IBase
{
public:
virtual void func3()=0;
};

class B:public b
{
public:
void func1(){}
void func2(){}
void func3(){}
};
b*_bp=new B;
b->func1();
b->func2();
b->func3();
ytfhwfnh 2007-03-05
  • 打赏
  • 举报
回复
你这么些子类通过什么抽象概念将它们连接在一起呢?如果出现你所说的情况的话,就应该考虑重新设计了,模式不能死搬硬套,视情况而定。
believefym 2007-03-05
  • 打赏
  • 举报
回复
子类如果扩展了,就不能再用通过接口进行多态的调用了
byteman_daydayup 2007-03-05
  • 打赏
  • 举报
回复
如果我有许多子类,各个子类需要不同的扩展,那么添加如此多的空方法到父类中,这样好吗??
我还是初学者,很多东西的理解都是靠凭空想象,不对的地方还请指正

5,530

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧