che*_*ers 4 c++ design-patterns
我有一个代表火车的数据结构,它可以由许多类型的汽车组成,例如火车引擎,谷物汽车,乘用车等等:
struct TrainCar {
// ...
Color color;
std::string registration_number;
unsigned long destination_id;
}
struct PowerCar : TrainCar {
// ...
const RealPowerCar &engine;
}
struct CargoCar : TrainCar {
// ...
const RealCargoCar &cargo;
bool full;
}
std::vector<TrainCar*> cars;
cars.push_back(new TrainCar(...));
cars.push_back(new TrainCar(...));
cars.push_back(new CargoCar(...));
cars.push_back(new CargoCar(...));
cars.push_back(new CargoCar(...));
Run Code Online (Sandbox Code Playgroud)
算法将遍历列车中的汽车,并决定如何路由/分流每辆车(是否将其保留在列车中,将其移至列车中的另一个点,将其从列车中移除).此代码如下所示:
std::vector<TrainCar*>::iterator it = cars.begin();
for (; it != cars.end(); ++it) {
PowerCar *pc = dynamic_cast<PowerCar*>(*it);
CargoCar *cc = dynamic_cast<CargoCar*>(*it);
if (pc) {
// Apply some PowerCar routing specific logic here
if (start_of_train) {
// Add to some other data structure
}
else if (end_of_train && previous_car_is_also_a_powercar) {
// Add to some other data structure, remove from another one, check if something else...
}
else {
// ...
}
}
else if (cc) {
// Apply some CargoCar routing specific logic here
// Many business logic cases here
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定这种模式(使用dynamic_casts和if语句链)是否是处理不同类型的简单结构列表的最佳方法.使用dynamic_cast似乎不正确.
一种选择是将路由逻辑移动到结构(就像(*it) - > route(is_start_of_car,&some_other_data_structure ...)),但是如果可能的话我想将路由逻辑保持在一起.
有没有更好的方法来迭代不同类型的简单结构(没有方法)?或者我是否保持dynamic_cast方法?
对此的标准解决方案称为双重调度.基本上,您首先将算法包装在针对每种类型的汽车重载的单独函数中:
void routeCar(PowerCar *);
void routeCar(CargoCar *);
Run Code Online (Sandbox Code Playgroud)
然后,route在基类中添加一个纯虚拟汽车的方法,并在每个子类中实现:
struct TrainCar {
// ...
Color color;
std::string registration_number;
unsigned long destination_id;
virtual void route() = 0;
}
struct PowerCar : TrainCar {
// ...
const RealPowerCar &engine;
virtual void route() {
routeCar(this);
}
}
struct CargoCar : TrainCar {
// ...
const RealCargoCar &cargo;
bool full;
virtual void route() {
routeCar(this);
}
}
Run Code Online (Sandbox Code Playgroud)
你的循环看起来像这样:
std::vector<TrainCar*>::iterator it = cars.begin();
for (; it != cars.end(); ++it) {
(*it)->route();
}
Run Code Online (Sandbox Code Playgroud)
如果要在运行时选择不同的路由算法,可以将routeCar-functions 包装在抽象基类中,并为其提供不同的实现.然后,您将该类的相应实例传递给TrainCar::route.
| 归档时间: |
|
| 查看次数: |
1761 次 |
| 最近记录: |