这是我的第一个问题:)
我知道我不应该检查对象类型,而是使用dynamic_cast,但这不会解决我的问题。
我有一个名为Extension和接口的类,名为IExtendable和IInitializable,IUpdatable,ILoadable,IDrawable(后四个基本相同)。如果Extension实现IExtendable接口,它可以使用不同的Extension对象扩展自身。
问题是我想允许实现IExtendable的Extension只能使用与原始Extension实现相同接口的Extension进行扩展。
你可能不会那么糟糕,所以我试着用代码来解释它:
class IExtendable
{
public:
IExtendable(void);
void AddExtension(Extension*);
void RemoveExtensionByID(unsigned int);
vector<Extension*>* GetExtensionPtr(){return &extensions;};
private:
vector<Extension*> extensions;
};
class IUpdatable
{
public:
IUpdatable(void);
~IUpdatable(void);
virtual void Update();
};
class Extension
{
public:
Extension(void);
virtual ~Extension(void);
void Enable(){enabled=true;};
void Disable(){enabled=false;};
unsigned int GetIndex(){return ID;};
private:
bool enabled;
unsigned int ID;
static unsigned int _indexID;
};
现在想象我创建扩展的情况:
class MyExtension : public Extension, public IExtendable, public IUpdatable, public IDrawable
{
public:
MyExtension(void);
virtual ~MyExtension(void);
virtual void AddExtension(Extension*);
virtual void Update();
virtual void Draw();
};
我想允许这个类仅使用实现相同接口(或更少)的Extensions来扩展自身。例如,我希望它能够采用实现IUpdatable的Extension;或者IUpdatable和IDrawable;但是例如不是实现ILoadable的扩展。 我想这样做是因为例如Update()将在一些实现IExtendable和IUpdateable的Extension上调用,它也将在扩展此扩展的这些Extensions上调用。
所以,当我添加一些Extension实现IExtendable的扩展和一些IUpdatable,ILoadable ......我不得不检查是否要添加的Extension也实现了这些接口。所以在IExtendable :: AddExtension(Extension *)中,我需要做这样的事情:
void IExtendable::AddExtension(Extension* pEx)
{
bool ok = true;
// check wheather this extension can take pEx
// do this with every interface
if ((*pEx is IUpdatable) && (*this is_not IUpdatable))
ok = false;
if (ok) this->extensions.push_back(pEx);
}
但是怎么样?什么是最好的解决方案?我不想使用dynamic_cast并查看它是否返回null ...谢谢
答案 0 :(得分:6)
你应该重新考虑你的设计。如果您需要此行为,可能会引入IUpdateExtendable
和IDrawExtendable
。
当前方法不好的原因是它违反了Liskov Substitution Principle。你基本上是说“这个对象充当了IExtendable,但实际上并没有,除非....”如果一个类实现了一个接口,那么它真的应该可以通过该接口使用而不需要任何条件。如果不是,那就是等待发生的维护噩梦。
答案 1 :(得分:0)
只是一种直觉,但根据您的扩展程序的作用,visitor-pattern可能会对您有所帮助。您可能还想阅读decorator模式。
答案 2 :(得分:0)
我可以将所有这些接口合并到一个类中,所以我会得到这样的东西:
class Extension
{
public:
Extension(void);
virtual ~Extension(void);
void AddExtension(Extension* pEx){extensions.push_back(pEx);};
virtual void Initialize()
{
for each (Extension* pEx in extensions) pEx->Initialize();
};
virtual void Load()
{
for each (Extension* pEx in extensions) pEx->Load();
};
virtual void Update()
{
for each (Extension* pEx in extensions) pEx->Update();
};
virtual void Draw()
{
for each (Extension* pEx in extensions) pEx->Draw();
};
private:
vector<Extension*> extensions;
};
但这意味着将在每个添加的扩展上调用所有方法。例如。一些添加的扩展中的空方法不会加载任何内容而不会绘制任何内容。