以一个简单的项目来学习面向对象编程(设计模式和多线程)

下面的项目是两年前学校老师布置的一个小项目,当时自己用了一种很笨拙的方式实现了,现在用面向对象的思想和多线程重构这个项目。

问题描述:

西宝高速仿真模拟 西安市到宝鸡市之间是我省主要的高速公路客运路线之一,经过简化后的客运路线端点、中途停靠点和里程如下图所示(括号里是简称,里程的单位是公里):

限定条件 (1) 从XN始发至BJ的客车和从BJ始发至XN的客车均有两种车型:沃尔沃(限定乘客人数为40人);依维柯(限定乘客人数为21人)。沃尔沃的速度为2公里/分钟,依维柯的速度为1.4公里/分钟。 (2) 起始状态时,XN拥有沃尔沃和依维柯客车分别为XNW和XNY辆,BJ拥有沃尔沃和依维柯客车分别为BJW和BJY辆。 (3) 从XN至BJ和从BJ至XN的沃尔沃,均为上午8:30开始,每小时一班,最后一班为下午5:30;从XN至BJ和从BJ至XN的依维柯,均为上午8:00开始,每20分钟一班,最后一班为下午6:00。 (4) 从XN至BJ的客车到达BJ后,即成为从BJ至XN的客车,排在当时BJ同类车型的队尾,再按(3)确定发车时间;从BJ至XN的客车到达XN后的规则相同。 (5) 只考虑途中只有乘客下车、没有乘客上车的情况。 (6) 有乘客下车时,,不论方向与车型,停车时间统一为2分钟。 (7) 乘坐从XN至BJ客车的乘客,其下车点为XY、XP、WG、CP、GZ和BJ的可能性分别为P_XBXY、P_XBXP、P_XBWG、P_XBCP、P_XBGZ和P_XBBJ。这些可能性之和为1;乘坐从BJ至XN客车的乘客,其下车点为GZ、CP、WG、XP、XY和XN的可能性分别为P_BXGZ、P_BXCP、P_BXWG、P_BXXP、P_BXXY和P_BXXN。这些可能性之和为1。

需仿真的活动 (1) 从上午7:30开始到下午5:59为止,每分钟分别在XN和BJ随机产生去往BJ和XN方向的新到达的乘客。每分钟达到的人数范围为0~PN人。 (2) 按照限定条件(7)的规定,随机产生新到达的乘客的目的地。 (3) 乘客按到达的先后顺序上最近一辆(依照限定条件(3)的规定)始发的客车,若该车客满则等候下一辆始发的客车。 (4) 若客车到达中途停靠站时有乘客在此下车,按限定条件(5)和(6)处理,否则不停车继续行驶。

我们逐步分析最关键的点: 我们先仅仅模拟一辆客车从西安到宝鸡的过程,中途遇到的中间站停车2分,没有乘客参与,仅仅是让这辆客车从西安跑到宝鸡。

这个简单的问题,直观的解决方案是:一个大循环,每次循环时间更新一次,在循环内更新客车的位置,判断客车时候到达中间站或终点站。这种解决方式思想简单,但是可扩展性差,若有新种类的客车,则我们需要重新改写主逻辑。

我们用面向对象的思维来分析这个简单的仿真模拟过程,实际上就是客车启动、行驶、中途停车、结束。这几个状态间的转化。可以用状态模式来解决这个问题。

思路: 客车类接收外界传入的时间,其初始时调用启动状态指针,并把自己作为参数传入,状态类根据外界条件(时间)和规则(客车时刻表),来判断出下个状态是什么(并更新客车类中保存的状态码)完成状态转换。 这样,客车只是一直调用其当前状态码对应的状态指针来运行逻辑,(状态类对象指针的函数悄悄地改变了客车类中的当前状态码,这样,在客车不知不觉地过程中,完成了状态的转换)

class Vehicle{public:Vehicle(){_brand = “Volvo” ;_identifier = 1 ;_speed = 2 ;_driveDirect = FORWARD ;_curStateNo = 0 ;_curPos = 0 ;}int Init(const Time& curTime) ;//runint Running(const Time& curTime) ;//根据当前时间,返回vehicle当前状态:起点start、路上running、中间站停车midStop、终点endStopint GetVehicleState(const Time& curTime) ;private:_speed ;_curStateNo ;//当前Vehicle所处状态码DirectKind _driveDirect ;::map<int, VehicleState*> _vehicleStateMap ;//Vehicle运行时间表(每一站的到达时间和发车时间)std::vector<std::pair<Time, std::string> > _vehicleSchedule ;//改变当前状态VehicleState* ChangeState(int destStateNo) ;//计算运行时刻表int CalcVehicleSchedule(const Time& startTime, const DirectKind& driveDirect) ;friend class VehicleState ;} ;

客车对外的接口只有running(); 而running所做的工作只是调用当前客车状态指针的process函数,并把自己和当前时间作为参数传入。 把主要的逻辑和处理交给客车状态对象去做。

int Vehicle::Running(const Time& curTime){int ret ;ret = _vehicleStateMap[_curStateNo]->Process(this, curTime);if (ret == -1)return -1 ;return 0 ;} //客车状态类//交通工具接口(抽象类)class VehicleState{public:VehicleState() {}virtual int Process(Vehicle* pVehicle, const Time& curTime) = 0 ;protected:int ChangeState(Vehicle* pVehicle , int destStateNo);} ;//启动状态class StartState : public VehicleState{public:int Process(Vehicle* pVehicle, const Time& curTime) ;} ;//行驶状态class RunningState : public VehicleState{public:int Process(Vehicle* pVehicle, const Time& curTime) ;} ;//中途停车状态class MidStopState : public VehicleState{public:int Process(Vehicle* pVehicle, const Time& curTime) ;} ;//到站停车状态class EndStopState : public VehicleState{public:int Process(Vehicle* pVehicle, const Time& curTime) ;} ;穿越茫茫人海,寻找属于我们的那一份宁静。

以一个简单的项目来学习面向对象编程(设计模式和多线程)

相关文章:

你感兴趣的文章:

标签云: