分解思想和抽象思想

理解松耦合的设计思想。

理解设计原则比掌握某一个具体的设计模式更重要。

设计模式伴随的方法 —— 重构。

面向对象的设计模式 —— GOF 23 种为主干。


为什么要设计模式?解决不断重复的问题。可复用是面向对象的目标。94年《设计模式:可复用面向对象软件的基础》。

底层思维:向下,从机器底层微观上理解对象构造。1. 语言构造 2. 编译转换 3. 内存模型 4. 运行机制。 语言层面上的对象机制:封装,继承,多态。

抽象思维:向上,现实世界抽象为程序代码。1. 架构领域的架构模式; 2. 数据库领域的数据库模式;3. 组件封装; 4. 面向对象。 掌握好什么是“好的面向对象设计”。


解决复杂问题的方法:1.分解 2.抽象

分解

大问题分解为若干个小问题,复杂问题分解为若干个简单的问题。C语言,结构性语言是典型的分解思想。

代码示例:

#include <iostream>
#include <vector>

using namespace std;


/****************************/

class Point {
public:
    int x;
    int y;
};

// 直线
class Line
{
public:
    Point start;
    Point end;

    Line(const Point &start, const Point &end)
    {
        this->start = start;
        this->end = end;
    }
};

// 矩形
class Rect
{
public:
    Point leftUp;
    int width;
    int height;

    Rect(const Point& leftUp, int width, int height)
    {
        this->leftUp = leftUp;
        this->width = width;
        this->height = height;
    }
};


// 增加一个类
class Circle
{

};

/*************************/

enum class Shape
{
    Line,
    Rect,
    Circle,
};

class MainForm
{
public:
    MainForm() {}

    virtual void OnMouseDown(const int x, const int y)
    {
        p1.x = x;
        p1.y = y;
    }
    virtual void OnMouseUp(const int x, const int y, Shape shape)
    {
        p2.x = x;
        p2.y = y;

        switch (shape)
        {
        case Shape::Line:
        {
            lineVector.push_back(Line(p1, p2));
        }
        break;
        case Shape::Rect:
        {
            rectVector.push_back(Rect(p1, p2.x - p1.x, p2.y - p1.y));
        }
        break;
        // 改变
        case Shape::Circle:
        {
            // ....
        }
        break;
        default:
            break;
        }

    }
    virtual void OnPaint()
    {//刷新

        // 针对直线
        for (int i = 0; i < lineVector.size(); i++) {
            cout << "直线,起点(" << lineVector[i].start.x << "," << lineVector[i].start.y << ") " <<
                "终点(" << lineVector[i].end.x << "," << lineVector[i].end.y << ")" << endl;
        }

        cout << endl;

        // 针对矩形
        for (int i = 0; i < rectVector.size(); i++) {
            cout << "矩形,起点(" << rectVector[i].leftUp.x << "," << rectVector[i].leftUp.y << ")" <<
                "宽度:" << rectVector[i].width << "高度:" << rectVector[i].height << endl;
        }

        // 改变  针对圆
        for (;;) {
            // ....
            break;
        }
    }

private:
    Point p1;
    Point p2;

    // 数据结构存放
    vector<Line> lineVector;
    vector<Rect> rectVector;
    //改变
    vector<Circle> circleVector;
};

/*********************************/

int main()
{
    MainForm mainForm;

    // 画直线
    mainForm.OnMouseDown(0, 0);
    mainForm.OnMouseUp(100, 100, Shape::Line);
    mainForm.OnMouseDown(0, 0);
    mainForm.OnMouseUp(110, 110, Shape::Line);

    // 画矩形
    mainForm.OnMouseDown(10, 10);
    mainForm.OnMouseUp(1000, 1000, Shape::Rect);
    mainForm.OnMouseDown(100, 100);
    mainForm.OnMouseUp(1000, 1000, Shape::Rect);

    // 刷新
    mainForm.OnPaint();

    getchar();
    return 0;
}

输出:

直线,起点(0,0) 终点(100,100)
直线,起点(0,0) 终点(110,110)

矩形,起点(10,10)宽度:990高度:990
矩形,起点(100,100)宽度:900高度:900

如上,如果要新增一个画圆的功能,有很多地方需要去修改改变代码。

抽象

处理复杂性有一个通用的技术,即抽象。由于不能掌握全部的复杂对象,我们选择忽视它的非本质细节,而去处理泛化和理想化了的对象模型。

面向对象的设计模式,基本上是围绕着抽象这个概念去进行的。

代码示例:

#include <iostream>
#include <vector>
#include <math.h>

using namespace std;


/****************************/

class Point {
public:
    int x;
    int y;
};

// 接口
class IShape {
public:
    virtual void Draw() = 0;
    virtual ~IShape() { }
};

// 直线
class Line : public IShape
{
public:
    Point start;
    Point end;

    Line(const Point &start, const Point &end)
    {
        this->start = start;
        this->end = end;
    }

    // 自己画自己,类功能,各司其职。
    virtual void Draw() override
    {
        cout << "直线,起点(" << start.x << "," << start.y << ") " <<
            "终点(" << end.x << "," << end.y << ")" << endl;
    }
};

// 矩形
class Rect : public IShape
{
public:
    Point leftUp;
    int width;
    int height;

    Rect(const Point& leftUp, int width, int height)
    {
        this->leftUp = leftUp;
        this->width = width;
        this->height = height;
    }

    virtual void Draw() override
    {
        cout << "矩形,起点(" << leftUp.x << "," << leftUp.y << ")" <<
            "宽度:" << width << " 高度:" << height << endl;
    }
};


// 增加一个类
class Circle : public IShape
{
public:
    Point m_center;
    int R;
    Circle(const Point &center, int r) :m_center(center), R(r) {}

    virtual void Draw() override
    {
        cout << "圆形,圆心(" << m_center.x << "," << m_center.y << ")" <<
            "半径:" << R << endl;
    }
};

/*************************/

enum class ShapeType
{
    Line,
    Rect,
    Circle,
};

class MainForm
{
public:
    MainForm() {}
    virtual ~MainForm()
    {
        vector<IShape *>::iterator itor = m_ShapeVector.begin();
        while (itor != m_ShapeVector.end()) {
            delete (*itor);
            *itor = nullptr;
            itor = m_ShapeVector.erase(itor);
            itor++;
        }
    }

    virtual void OnMouseDown(const int x, const int y)
    {
        p1.x = x;
        p1.y = y;
    }
    virtual void OnMouseUp(const int x, const int y, ShapeType shape)
    {
        p2.x = x;
        p2.y = y;

        switch (shape)
        {
        case ShapeType::Line:
        {
            m_ShapeVector.push_back(new Line(p1, p2));
        }
        break;
        case ShapeType::Rect:
        {
            m_ShapeVector.push_back(new Rect(p1, p2.x - p1.x, p2.y - p1.y));
        }
        break;
        // 改变     后面这里用工厂模式,都不用修改
        case ShapeType::Circle:
        {
            double r = sqrt((p2.x - p1.x) *  (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
            m_ShapeVector.push_back(new Circle(p1, static_cast<int>(r)));
        }
        break;
        default:
            break;
        }

    }
    virtual void OnPaint()
    {//刷新
        for (int i = 0; i < m_ShapeVector.size(); i++) {
            m_ShapeVector[i]->Draw(); // 多态调用
        }
    }

private:
    Point p1;
    Point p2;

    // 数据结构存放
    vector<IShape *> m_ShapeVector;
};

/*********************************/

int main()
{
    MainForm mainForm;

    // 画直线
    mainForm.OnMouseDown(0, 0);
    mainForm.OnMouseUp(100, 100, ShapeType::Line);
    mainForm.OnMouseDown(0, 0);
    mainForm.OnMouseUp(110, 110, ShapeType::Line);

    // 画矩形
    mainForm.OnMouseDown(10, 10);
    mainForm.OnMouseUp(1000, 1000, ShapeType::Rect);
    mainForm.OnMouseDown(100, 100);
    mainForm.OnMouseUp(1000, 1000, ShapeType::Rect);

    // 画圆
    mainForm.OnMouseDown(100, 100);
    mainForm.OnMouseUp(1000, 1000, ShapeType::Circle);
    mainForm.OnMouseDown(101, 101);
    mainForm.OnMouseUp(1100, 1100, ShapeType::Circle);

    // 刷新
    mainForm.OnPaint();

    getchar();
    return 0;
}

输出:

直线,起点(0,0) 终点(100,100)
直线,起点(0,0) 终点(110,110)
矩形,起点(10,10)宽度:990 高度:990
矩形,起点(100,100)宽度:900 高度:900
圆形,圆心(100,100)半径:1272
圆形,圆心(101,101)半径:1412

抽象能够很好的应对引入一种变化的情况。复用性比较好,分解改的地方太多。

什么是好的软件设计?软件设计的金科玉律:复用!




参考:GeekBand

posted @   double64  阅读(71)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2021-09-24 C# WInform 通过委托跨窗体传值
2021-09-24 C# 模块封装的形式做一个加法计算器
2021-09-24 SQLServer数据库数据表的一些操作脚本
点击右上角即可分享
微信分享提示