我正在努力克服我目前的设计并且想知道,如果有可能在不使用铸造方法的情况下决定使用哪种方法。说我有一个基础Fence
课程。
此刻,我的工人知道如何建造木栅栏以及如何建造倒钩铁丝网围栏。他们可以在一起添加两个围栏......但到目前为止,他们只学会了如何将木制的木头连接到木制的围栏,以及倒钩的有线围栏和倒钩的围栏。
但是,由于他们可能会了解更多,因此Fence类具有虚拟addFence(const Fence& fence)
方法。
由于我想避免任何转换方法,我尝试在两个类中添加特殊的addFence()
方法。这是一个例子:
class Fence {
public:
virtual void addFence(const Fence& fence) = 0;
...
};
class BarbWireFence : public Fence {
public:
...
void addFence(const Fence& fence) {
//only add such a fence, if it is a barb wired one
}
void addFence(const BarbWireFence& fence) {
//continue the fence with the given one
}
};
class WoodenFence : public Fence {
public:
...
void addFence(const Fence& fence) {
//only add the fence, if it is a wooden one
}
void addFence(const WoodenFence& fence) {
//continue the fence with the given one
}
};
现在我想做一些像
这样的事情Fence *woodenFence1 = new WoodenFence();
Fence *woodenFence2 = new WoodenFence();
woodenFence1->addFence(*woodenFence2);
但由于它是运行时决定我有什么样的围栏,我只有基础Fence*
指针,因此在最后一行使用了基础class Fence
的定义
那么有更好的实施方案来自动决定吗?我有什么样的围栏?或者我应该使用完全不同的设计?
答案 0 :(得分:2)
我不知道C ++中的一般方法,但假设你有一组固定的派生类,你可以使用额外的间接来实际处理这种情况:
class BarbWireFence;
class WoodenFence;
class Fence {
public:
virtual void add(Fence& fence) = 0;
virtual void add(BarbWireFence& fence) = 0;
virtual void add(WoodenFence& fence) = 0;
};
class BarbWireFence {
void add(Fence& fence) override { fence.add(*this); }
void add(BarbWireFence& fence) override; // deal with the actual addition
void add(WoodenFence& fence) override; // deal with the actual addition
};
class WoodenFence {
void add(Fence& fence) override { fence.add(*this); }
void add(BarbWireFence& fence) override; // deal with the actual addition
void add(WoodenFence& fence) override; // deal with the actual addition
};
答案 1 :(得分:2)
欢迎来到binary methods的精彩世界。
这个问题没有令人满意的解决方案。您可能想了解double dispatch及其更正式的兄弟the Visitor pattern。这两件事情基本相同,只是略有不同。在最简单的场景中,您可以这样做:
class WoodenFence;
class BarbWireFence;
class Fence {
public:
virtual void addFence(const Fence& fence) = 0;
virtual void addMe(BarbWireFence& fence) const = 0;
virtual void addMe(WoodenFence& fence) const = 0;
...
};
class BarbWireFence : public Fence {
public:
...
void addFence(const Fence& fence) {
fence->addMe(*this);
}
void addMe(BarbWireFence& fence) const {
fence->addBarbWireFence(*this);
}
void addMe(WoodenFence& fence) const {
throw error("bad fence combo");
}
void addBarbWireFence(const BarbWireFence& fence) {
// actually add fence...
}
};
class WoodenFence : public Fence {
public:
...
void addFence(const Fence& fence) {
fence->addMe(*this);
}
void addMe(BarbWireFence& fence) const {
throw error("bad fence combo");
}
void addMe(WoodenFence& fence) const {
fence->addWoodenFenceFence(*this);
}
void addWoodenFence(const WoodenFence& fence) {
// actually add fence...
}
...
};
您可以弄清楚当您添加其他10种围栏类型时会发生什么。
可能会采取完全不同的方向,即对整个业务进行模板化并摆脱Fence基类,因为它没有提供类型安全的接口。
class BarbWireFence {
public:
...
void addSimilarFence(const BarbWireFence& fence) {
//continue the fence with the given one
}
};
class WoodenFence {
public:
...
void addSimilarFence(const WoodenFence& fence) {
//continue the fence with the given one
}
};
template <typename Fence>
void addFence (Fence& f1, const Fence& f2) {
f1->addSimilarFence(f2);
}