现在我需要在相同的上下文中使用Driver and Vehicle,每当我通过Driver时,给我默认的Car / Bus,每当我通过Vehicle时我都会this
。在这种情况下,在两者之上引入接口是一个坏主意吗?如果是的话,原因是什么?
修改:
答案 0 :(得分:1)
也许我误解了这个问题,但这是我的想法:
Vehicle
个,而不是Car
/ Bus
个对象 Vehicle
应该需要驱动程序的getter Vehicle::getDriver()
,Bus
和Car
个对象包含对Driver
的引用。无需在Driver
和Vehicle
之上引入接口。
C ++中快速未经测试的代码存根(包含错误~~),了解其中一些方法的实现方式:
class Driver;
// Vehicle interface
class Vehicle {
public:
virtual void setDriver(Driver* driver);
virtual Driver* getDriver() const;
/**
* Some exciting driving function!! :D
*/
virtual void drive();
};
class Car : public Vehicle {
Driver* m_driver = nullptr;
public:
void setDriver(Driver* driver) override { m_driver = driver; }
Driver* getDriver() const override { return m_driver; }
void drive() override { /* do something! */ }
};
class Bus : public Vehicle {
Driver* m_driver = nullptr;
public:
void setDriver(Driver* driver) override { m_driver = driver; }
Driver* getDriver() const override { return m_driver; }
void drive() override { /* do something! */ }
};
// Driver
class Driver {
int m_defIdx;
std::vector<Vehicle*> m_vehicles;
public:
void addVehicle(Vehicle* vehicle, bool setDefault = true) {
m_vehicles.push_back(vehicle);
vehicle->setDriver(this);
if (setDefault) m_defIdx = m_vehicles.length() - 1;
}
Vehicle* getDefaultVehicle() { return m_vehicles[m_defIdx]; }
Vehicle* getVehicle(int index) { return m_vehicles[index]; }
}
请注意,如果您使用的是C ++,那么智能指针可能是一个更好的主意,而不是接口,抽象类可能更有意义。
现在,我们来看看你如何与它进行交互。
void robBank(Driver& driver) {
/* do some totally criminal stuff! */
// run away!! Note that we can access the vehicle here.
driver.getDefaultVehicle()->drive();
}
int main() {
Driver sally;
Car* car = new Car();
sally.addVehicle(car, true);
robBank(sally);
delete car; // clean up after ourselves :)
}
请注意,即使我只传递Driver
到robBank()
,因为Driver
包含对Vehicle
的引用,Driver
对象公开这样,我们就可以访问Vehicle
。
在Driver
和Vehicle
Movable
,它可能具有Movable::move()
功能,因此驾驶员和车辆都可以四处移动。这是一个具有共同功能的概念,是composition over inheritance概念背后的关键。答案 1 :(得分:1)
我希望我能正确理解你的问题。
我不会在它们上面引入一个界面,因为它似乎并不反映您的域名。似乎很难想出一个名字。这不是一个好兆头。
您可以尝试策略模式,它可以帮助封装为您的上下文获取该Vehicle实例的过程。
在这种特定情况下,它可能是一种过度杀伤,但遗留代码可能会受益。
例如(C#)。
class Context {
public Vehicle Drive(DrivingStrategy strategy) {
//...
return strategy.GetDrivable();
}
}
abstract class DrivingStrategy {
public static DrivingStrategy For(Driver driver) {
//...
return new DriverDrivingStrategy(driver);
}
public static DrivingStrategy For(Vehicle vehicle) {
//...
return new VehicleDrivingStrategy(vehicle);
}
abstract public Vehicle GetDrivable();
}
class DriverDrivingStrategy : DrivingStrategy {
private readonly Driver driver;
public DriverDrivingStrategy(Driver driver) {
//...
this.driver = driver;
}
public override Vehicle GetDrivable() {
//Default vehicle logic can be potentially moved from Driver to this class.
return driver.GetDefaultVehicle();
}
}
class VehicleDrivingStrategy : DrivingStrategy {
private readonly Vehicle vehicle;
public VehicleDrivingStrategy(Vehicle vehicle) {
this.vehicle = vehicle;
}
public override Vehicle GetDrivable() {
return vehicle;
}
}
class Driver {
public Vehicle GetDefaultVehicle() {
//...
}
}
class Vehicle {
//...
}
客户端:
class Client {
public void Do() {
Context context = new Context();
Driver driver = new Driver();
Vehicle vehicle = new Vehicle();
context.Drive(DrivingStrategy.For(driver));
context.Drive(DrivingStrategy.For(vehicle));
}
}
当然,VehicleDrivingStrategy类没有做太多,你可以失去一个抽象的DrivingStrategy,并使VehicleDrivingStrategy成为其他类的基类。
此外,您可能希望扩展策略,不仅仅检索Vehicle实例,还要求他们为您的上下文做更多事情。它更适合用于该模式。与驾驶员策略一样:driver.GetDefaultVehicle().Drive()
/ this.GetDefaultVehicle().Drive()
和车辆:vehicle.Drive()
;