一次正交设计之旅

文章来自于刘光聪,实践了一把,觉得在代码设计上自己有如下收益:

  1. 多级容器封装;
  2. 分离变化方向;
  3. 依赖于稳定;
  4. C++私有继承堪称C++的必杀技之一。

原文章里面代码有编译错误,这里重新整理了一下,方便大家看。重构的思路可以看原文章:一次正交设计之旅

重构前的代码:

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);
}

重构后的代码:

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;
};

参考文献:

  1. 一次正交设计之旅
  2. C++ 私有继承
  3. 容器与封装 - 简书 (jianshu.com)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 遗留代码 假如存在一段遗留代码,使用vector<vector >表示了一个复杂的领域对象。程序包括计数与缓存两种...
    刘光聪阅读 2,273评论 0 15
  • 一个出发点 当谈起软件设计的目的时,能够获得所有人认同的答案只有一个:功能实现。 因为这是一个软件存在的根本原因。...
    _袁英杰_阅读 21,539评论 8 86
  • Design is there to enable you to keep changing the softwa...
    刘光聪阅读 8,962评论 5 57
  • 正交设计,是普遍的设计原则,与粒度无关,与编程范式无关,更与具体的实现语言无关。(虽然确实在不同的编程范式下,或使...
    _袁英杰_阅读 12,634评论 11 66
  • 大家好,我是十一。 前情回顾 上面一篇我们讲了错误推测法,我们先来回顾下: 错误推测法[https://www.j...
    觅识堂的十一阅读 3,287评论 0 1