[ RUN ] ElevatorTest.basic_test
1 3 9 12 2 32[2]
1 3 9 12 2 32[3]
1 3 9 12 2 32[4]
1 3 9 12 2 32[5]
1 3 9 12 2 32[6]
1 3 9 12 2 32[7]
1 3 9 12 2 32[8]
1 3 9 12 2 32[9]
1 3 9 12 2 32[10]
1 3 9 12 2 32[11]
1 3 9 12 2 32[12]
1 3 9 12 2 32[13]
1 3 9 12 2 32[14]
1 3 9 12 2 32[15]
1 3 9 12 2 32[16]
1 3 9 12 2 32[17]
1 3 9 12 2 32[18]
1 3 9 12 2 32[19]
1 3 9 12 2 32[20]
1 3 9 12 2 32[21]
1 3 9 12 2 32[22]
1 3 9 12 2 32[23]
1 3 9 12 2 32[24]
1 3 9 12 2 32[25]
1 3 9 12 2 32[26]
1 3 9 12 2 32[27]
1 3 9 12 2 32[28]
1 3 9 12 2 32[29]
1 3 9 12 2 32[30]
1 3 9 12 2 32[31]
1 3 9 12 2 32[32]
1 3 9 12 2[32]
1 3 9 12 2[31]
1 3 9 12 2[30]
1 3 9 12 2[29]
1 3 9 12 2[28]
1 3 9 12 2[27]
1 3 9 12 2[26]
1 3 9 12 2[25]
1 3 9 12 2[24]
1 3 9 12 2[23]
1 3 9 12 2[22]
1 3 9 12 2[21]
1 3 9 12 2[20]
1 3 9 12 2[19]
1 3 9 12 2[18]
1 3 9 12 2[17]
1 3 9 12 2[16]
1 3 9 12 2[15]
1 3 9 12 2[14]
1 3 9 12 2[13]
1 3 9 12 2[12]
1 3 9 12 2[11]
1 3 9 12 2[10]
1 3 9 12 2[9]
1 3 9 12 2[8]
1 3 9 12 2[7]
1 3 9 12 2[6]
1 3 9 12 2[5]
1 3 9 12 2[4]
1 3 9 12 2[3]
1 3 9 12 2[2]
1 3 9 12[2]
1 3 9 12[3]
1 3 9 12[4]
1 3 9 12[5]
1 3 9 12[6]
1 3 9 12[7]
1 3 9 12[8]
1 3 9 12[9]
1 3 9 12[10]
1 3 9 12[11]
1 3 9 12[12]
1 3 9[12]
1 3 9[11]
1 3 9[10]
1 3 9[9]
1 3[9]
1 3[8]
1 3[7]
1 3[6]
1 3[5]
1 3[4]
1 3[3]
1[3]
1[2]
1[1]
[1]
[1]
[1]
[1]
[1]
[1]
[1]
[1]
[1]
[1]
[1]
[1]
方括号[]里表示当前楼层,前面的数据表示将要去的楼层。这叫一个笨哦!
class EView {
public:
EView(){};
~EView() {};
void set_state(EState &state) { s_ = &state; }
void update()
{
for_each(s_->get_vector().begin(), s_->get_vector().end(), func);
std::cout << "[" << s_->get_cur_floor() << "]" << endl;
}
private:
static void func(int i) {
std::cout << ' ' << i;
}
public:
EState *s_;
};
虽然笨,但只需要修改EState类即可让算法变聪明。MVC的威力。改进后的输出:
从1楼走起
3 9 12 2 32[1]
3 9 12 2 32[2]
3 9 12 32[2]
3 9 12 32[3]
9 12 32[3]
9 12 32[4]
9 12 32[5]
9 12 32[6]
9 12 32[7]
9 12 32[8]
9 12 32[9]
12 32[9]
12 32[10]
12 32[11]
12 32[12]
32[12]
32[13]
32[14]
32[15]
32[16]
32[17]
32[18]
32[19]
32[20]
32[21]
32[22]
32[23]
32[24]
32[25]
32[26]
32[27]
32[28]
32[29]
32[30]
32[31]
32[32]
[32]
[32]
[32]
[32]
[32]
[32]
[32]
[32]
[32]
[32]
[32]
[32]
[32]
[32]
[32]
从9楼走起:
1 3 9 12 2 32[8]
1 3 9 12 2 32[7]
1 3 9 12 2 32[6]
1 3 9 12 2 32[5]
1 3 9 12 2 32[4]
1 3 9 12 2 32[3]
1 3 9 12 2 32[2]
1 3 9 12 2 32[1]
3 9 12 2 32[1]
3 9 12 2 32[2]
3 9 12 32[2]
3 9 12 32[3]
9 12 32[3]
9 12 32[4]
9 12 32[5]
9 12 32[6]
9 12 32[7]
9 12 32[8]
9 12 32[9]
12 32[9]
12 32[10]
12 32[11]
12 32[12]
32[12]
32[13]
32[14]
32[15]
32[16]
32[17]
32[18]
32[19]
32[20]
32[21]
32[22]
32[23]
32[24]
32[25]
32[26]
32[27]
32[28]
32[29]
32[30]
32[31]
32[32]
[32]
[32]
[32]
[32]
[32]
[32]
全部代码如下:
/*
* (C) 1999-2013 Alibaba Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*
* Version: elevator.cpp, 04/18/2014 03:41:33 PM Yu Huang Exp $
*
* Author:
* Huang Yu <xiaochu.yh@alipay.com>
* Description:
*
*
*/
#include <gtest/gtest.h>
#include "tbsys.h"
#include <vector>
#include <algorithm> // std::for_each
using namespace std;;
using namespace tbsys;;
/*
Elevator
M: IState
C: EControl
V: EView
*/
class IState;
class EView;
class EControl;
class IState {
public:
IState() : cur_floor_(9) {}
virtual bool need_stop() = 0;
virtual bool need_open() = 0;
virtual void move() = 0;
virtual void open() = 0;
int get_cur_floor() { return cur_floor_; }
vector<int> & get_vector() { return targets_;}
void set_speed(int speed) { speed_ = speed; }
int get_speed() { return speed_; }
void push_floor(int floor) { targets_.push_back(floor); }
protected:
int cur_floor_;
int speed_;
std::vector<int> targets_;
};
class ESimpleState : public IState {
public:
bool need_stop()
{
return targets_.empty();
}
bool need_open()
{
bool open = false;
if ((!targets_.empty()) && targets_.back() == cur_floor_)
{
open = true;
}
return open;
}
void move()
{
if (targets_.empty())
{
}
else if (targets_.back() > cur_floor_)
{
cur_floor_++;
}
else if (targets_.back() < cur_floor_)
{
cur_floor_--;
}
}
void open()
{
targets_.pop_back();
}
};
class EBetterState : public IState {
public:
bool need_stop()
{
return targets_.empty();
}
bool need_open()
{
bool open = false;
pair<vector<int>::iterator,vector<int>::iterator> p = minmax_element(targets_.begin(), targets_.end());
if ((!targets_.empty()) && (*p.first == cur_floor_ || *p.second == cur_floor_))
{
open = true;
}
return open;
}
void move()
{
if (targets_.empty())
{
}
else
{
pair<vector<int>::iterator,vector<int>::iterator> p = minmax_element(targets_.begin(), targets_.end());
if (*p.first > cur_floor_)
{
cur_floor_++;
}
else if (*p.second < cur_floor_)
{
cur_floor_--;
}
else
{
cur_floor_--;
}
}
}
void open()
{
pair<vector<int>::iterator,vector<int>::iterator> p = minmax_element(targets_.begin(), targets_.end());
if (*p.first == cur_floor_)
{
targets_.erase(p.first);
}
else if (*p.second == cur_floor_)
{
targets_.erase(p.second);
}
}
};
class EView {
public:
EView(){};
~EView() {};
void set_state(IState &state) { s_ = &state; }
void update()
{
for_each(s_->get_vector().begin(), s_->get_vector().end(), func);
std::cout << "[" << s_->get_cur_floor() << "]" << endl;
}
private:
static void func(int i) {
std::cout << ' ' << i;
}
public:
IState *s_;
};
class EControl : public tbsys::CDefaultRunnable
{
public:
virtual void run(tbsys::CThread *thread, void *arg)
{
UNUSED(thread);
UNUSED(arg);
int tick = 100;
while (tick--)
{
if (s_->need_stop())
{
}
else if (s_->need_open())
{
s_->open();
}
else
{
s_->move();
}
update_view();
sleep(1);
}
}
void set_state(IState &state) { s_ = &state; }
void set_view(EView &view) { v_ = &view; }
private:
void update_view()
{
v_->update();
}
private:
EView *v_;
IState *s_;
};
class ElevatorTest : public ::testing::Test
{
public:
ElevatorTest();
virtual ~ElevatorTest();
virtual void SetUp();
virtual void TearDown();
private:
// disallow copy
ElevatorTest(const ElevatorTest &other);
ElevatorTest& operator=(const ElevatorTest &other);
private:
// data members
};
ElevatorTest::ElevatorTest()
{
}
ElevatorTest::~ElevatorTest()
{
}
void ElevatorTest::SetUp()
{
}
void ElevatorTest::TearDown()
{
}
TEST_F(ElevatorTest, basic_test)
{
EBetterState m;
//ESimpleState m;
EControl c;
EView v;
c.set_state(m);
v.set_state(m);
c.set_view(v);
m.push_floor(1);
m.push_floor(3);
m.push_floor(9);
m.push_floor(12);
m.push_floor(2);
m.push_floor(32);
c.start();
c.wait();
TBSYS_LOG(INFO, "end exec");
}
int main(int argc, char **argv)
{
TBSYS_LOGGER.setLogLevel("INFO");
::testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}