文章來自于劉光聰,實(shí)踐了一把,覺得在代碼設(shè)計(jì)上自己有如下收益:
- 多級容器封裝;
- 分離變化方向;
- 依賴于穩(wěn)定;
- C++私有繼承堪稱C++的必殺技之一虫几。
原文章里面代碼有編譯錯(cuò)誤,這里重新整理了一下挽拔,方便大家看辆脸。重構(gòu)的思路可以看原文章:一次正交設(shè)計(jì)之旅
重構(gòu)前的代碼:
static vector<vector<int>> getFlaggedCells(vector<vector<int>>& board)
{
vector<vector<int>> result;
for (auto x : board)
{
if (x[0] == 4)
{
result.push_back(x);
}
}
return result;
}
int countFlaggedCells(vector<vector<int>>& board)
{
vector<vector<int>> result = getFlaggedCells(board);
return result.size();
}
static vector<vector<int>> getUnflaggedCells(vector<vector<int>>& board)
{
vector<vector<int>> result;
for (auto x : board)
{
if (x[0] == 3)
{
result.push_back(x);
}
}
return result;
}
int countUnflaggedCells(vector<vector<int>>& board)
{
vector<vector<int>> result = getUnflaggedCells(board);
return result.size();
}
static vector<vector<int>> getAliveCells(vector<vector<int>>& board)
{
vector<vector<int>> result;
for (auto x : board)
{
if (x[0] == 2)
{
result.push_back(x);
}
}
return result;
}
int countAliveCells(vector<vector<int>>& board)
{
vector<vector<int>> result = getAliveCells(board);
return result.size();
}
// global variable
vector<vector<int>> store;
void saveAliveCells(vector<vector<int>>& board)
{
store = getAliveCells(board);
}
重構(gòu)后的代碼:
enum State
{ INIT,SELECTED,ALIVE,FLAGGED };
struct Cell
{
bool flagged() const
{
return master() == FLAGGED;
}
bool alive() const
{
return master() == ALIVE;
}
private:
State master() const
{
return states.front();
}
private:
vector<State> states;
};
struct CellCollector
{
virtual void add(const Cell& cell) = 0;
virtual ~CellCollector()
{
}
};
// 公有繼承
template<typename Pred>
struct CellCounter :CellCollector
{
CellCounter(Pred pred) :num(0), pred(pred)
{
}
int get() const
{
return num;
}
private:
void add(const Cell& cell)
{
if (pred(cell))
++num;
}
private:
int num;
Pred pred;
};
struct GameBoard
{
int countFlaggedCells() const
{
return count([](const Cell& cell){
return cell.flagged();
});
}
int countUnflaggedCells() const
{
return count([](const Cell& cell){
return !cell.flagged();
});
}
int countAliveCells() const
{
return count([](const Cell& cell){
return cell.alive();
});
}
void List(CellCollector& col) const
{
for (auto &cell : cells)
{
col.add(cell);
}
}
private:
template<typename Pred>
int count(Pred pred) const
{
CellCounter<Pred> counter(pred);
List(counter);
return counter.get();
}
private:
vector<Cell> cells;
};
// 私有繼承
struct CellStore :private CellCollector
{
void save(const GameBoard& board)
{
board.List(*this);
}
private:
void add(const Cell& cell)
{
if (cell.alive())
cache.push_back(cell);
}
private:
vector<Cell> cache;
};