交互类 - 组织代码

时间:2010-07-22 08:59:44

标签: c++ design-patterns inheritance polymorphism

我在正确组织课程时遇到了一些问题。

假设我有一些ABase类。当我想创建这个类的一些不同的(更具体的)抽象(表示它是AParticular)时,我可以使用继承或只是组合。然后很容易将AParticular视为ABase:在继承的情况下它是自动生成的,在组合的情况下我可以创建一些const ABase& AParticular::GetABasePart()方法。通过这个我避免代码重复并获得多态功能。

但是,当我有两个或更多相互交互的类时,我会遇到一些问题,需要在更具体的抽象中创建这些类的类似物。 例如,假设我有两个类Car和Station。车站有一些维护汽车的公共方法:

class Car {
  ...
}

class Station {
  ...
  void AddCarToPlaceNumberN(const Car& car, int place_number) {
    // adds car to some_container<Car>.
  }
  Car* GetMutableCarPointer(int place_number) {
    // gets mutable pointer from some_container<Car>.
  }
  ...
  some_container<Car> cars;
}

现在,我想创建Truck和TruckStation类:它们非常类似于Car和Station类,并且进行了微小的更改。要理解问题就足够了,因为它们与Car和Station类完全相同,但它们的方法有一些其他名称(即TruckStation :: AddTruckToPlaceNumberN而不是Station :: AddCarToPlaceNumberN)

如何组织新类的代码以提供这些功能?

  1. 没有代码重复,我想使用已经创建的Car and Station类方法。
  2. 快速转换卡车&amp; - &GT; Car&amp;,TruckStation&amp; - &GT;站放大器; (没有必要的继承,组成也适合),因为我有时会把卡车当作Car和TruckStation一样对待车站。
  3. 级别Car-Station中的所有交互方法都应该在新的卡车 - TruckStation中实现。
  4. 主要问题是3d项目。让我们考虑两种交互方法:

    1)这种方法没问题:

    // If we use inheritance in creating Truck and TruckStation, then we just run
    void TruckStation::AddTruckToPlaceNumberN(const Truck& car, int place_number) {
       AddCarToPlaceNumberN(car, place_number)
    }
    // If we use composition, then it is appropriate to run sth like that:
    void TruckStation::AddTruckToPlaceNumberN(const Truck& car, int place_number) {
       station_.AddCarToPlaceNumberN(car.GetCarPart(), place_number);
    }
    

    2)但我不知道如何实现Station :: GetMutableCarPointer()的模拟:

    // For example, if TruckStation was inherited from Station, then suppose:
    Truck* TruckStation::GetMutableTruckPointer() {
       Car* car = GetMutableCarPointer();
       // Ups! I need to return Truck*, not Car*.
    }
    

    重复问题:我如何实现这些类来提供:

    1. 没有代码重复。
    2. 将新课程视为更高层次的抽象的可能性。
    3. 与Station :: GetMutableCarPointer()对应的TruckStation :: GetMutableTruckPointer()等实现方法。
    4. TNX!

2 个答案:

答案 0 :(得分:1)

具体到您的代码。我会这样做。

  1. 基础类车辆由汽车和卡车的特定类扩展。
  2. Class Station with methods
    • void Station::AddVehicleToPlaceNumberN(const Vehicle& vehicle, int placeNumber)
    • Vehicle* Station::GetMutableVehiclePointer()
  3. 设计/班级组织背后的原因。 1.仅在需要不同实现时才使用继承。如果继承方法的不同实现执行相同的操作(例如AddVehicleToPlaceNumberN的情况),则不需要分离实现。 2.使用通用方法名称总是有助于简化代码。方法可以重载(使用不同数量和类型的参数传递)以完成特定的事情。

答案 1 :(得分:1)

懒惰的方法是让电台使用通用类型T这样; (请耐心等待,我对C ++继承语法并不完全清楚,但原则适用)

template<typename T>
class Station<T>:CarStation
{
    void Station<T>::StatAddCarToPlaceNumberN(const T& car, int place_number)
    {
    // adds car to some_container<T>.
    }

    T * Station<T>::GetMutableCarPointer(int place_number) 
    {
        // gets mutable pointer from some_container<Car>.
        return dynamic_cast<T>(car);
    }
}

有一个抽象的超类Station,它实现了一个返回基指针的函数,比如说

class CarStation
{
    //...
    some_container<Car> cars;
    virtual Car * CarStation::GetMutableCarBasePointer(int place_number) = 0;

}

Car * CarStation::GetMutableCarBasePointer(int place_number)
{
       //gets mutable pointer to base class from some_container<T>
}

现在,如果你愿意,你可以创建一个新类TruckStation(我在C ++中不确定,再次,我称之为原理)

class TruckStation : Station<Truck>
{
   //...
}

或者只使用Station<Truck>