重新认识面向对象

news2024/12/29 9:49:49

一、重新认识面向对象

  • 1、重新认识面向对象
    • 1.1、理解隔离的变化
    • 1.2、各司其职
    • 1.3、对象是什么
  • 2、面向对象设计基本原则(八个原则)
    • 先介绍分而治之的思想构造类
    • 介绍抽象类的方法构造类
    • 2.1、依赖倒置原则(DIP )
    • 2.2、开放封闭原则(OCP )
    • 2.3、单一职责原则(SRP)
    • 2.4、Liskov替换原则(LSP)
    • 2.5、接口隔离原则(ISP)
    • 2.6、优先使用对象组合,而不是类继承
    • 2.7、封装变化点
    • 2.8、针对接口编程,而不是针对实现编程
  • 3、接口标准化
    • 3.1、以史为鉴(1)
    • 3.2、以史为鉴(2)
  • 4、将设计原则提升为设计经验
    • 4.1、设计习语Design Idioms
    • 4.2、设计模式Design Patterns
    • 4.3、架构模式Architectural Patterns
  • 5、模型分类
    • 5.1、GOF-23分类
      • 根据目的来分
      • 根据作用范围来分
    • 5.2、从封装变化角度对模式分类
  • 6、重构关键技法

1、重新认识面向对象

1.1、理解隔离的变化

  • 从宏观层面来看,面向对象的构建方式更能适应软件的变化,能将变化所带来的影响减为最小。

1.2、各司其职

  • 从微观层面来看,面向对象的方式更强调各个类的“责任“。
  • 由于需求变化导致的新增类型不应该影响原来类型的实现——是所谓各负其责。

1.3、对象是什么

  • 从语言实现层面来看,对象封装了代码和数据。
  • 从规格层面讲,对象是一系列可被使用的公共接口。
  • 从概念层面讲,对象是某种拥有责任的抽象。

2、面向对象设计基本原则(八个原则)

先介绍分而治之的思想构造类

点、直线矩形的类

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

MainForm

class MainForm
{
private:
    vector<Line> lineVector;
    vector<Rect> rectVector;

public:
    void addLine(const Line& line) { lineVector.push_back(line); }
    void addRect(const Rect rect) { rectVector.push_back(rect); }

    void run();
};

void MainForm::run()
{
	// 画直线
    for (int i = 0; i < lineVector.size(); i ++ )
    {
        drawLine(
            red, 
            lineVector[i].start.x, 
            lineVector[i].start.y;
            lineVector[i].end.x;
            lineVector[i].end.y;
        );
    }
	
	// 画矩形
    for (int i = 0; i < rectVector.size(); i ++ )
    {
        drawRect(
            red, 
            rectVector[i].leftUp, 
            rectVector[i].width, 
            rectVector[i].height
        );
    }
}

不难发现我们如果需要增加一个画圆形的方法就要修改MainForm类的很多代码

介绍抽象类的方法构造类

Shape抽象类、点、直线矩形的类

class Shape
{
public:
    virtual void draw() = 0;
    virtual ~Shape() {};
};

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

class Line : public Shape
{
public:
    Point start;
    Point end;

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

    void draw()
    {
        drawLine(
            red, 
            start.x,
            start.y,
            end.x,
            end.y
        );
    }
};


class Rect : public Shape
{
public:
    Point leftUp;
    int width;
    int height;

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


    void draw()
    {
        drawRect(
            red, 
            rectVector[i].leftUp, 
            rectVector[i].width, 
            rectVector[i].height
        );
    }
};

MainForm

class MainForm
{
private:
	// 使用基类指针
    vector<Shape*> ShapeVector;

public:
    void add(Shape* shape)
    {
        ShapeVector.push_back(shape);
    }
    void run();
};

void MainForm::run()
{
	// 只需要调用虚函数方法
    for (int i = 0; i < ShapeVector.size(); i ++ )
    {
        ShapeVector[i]->draw();
    }
}

2.1、依赖倒置原则(DIP )

  • 高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定)。
  • 抽象(稳定)不应该依赖于实现细节(变化),实现细节应该依赖于抽象(稳定)。
    在这里插入图片描述

2.2、开放封闭原则(OCP )

  • 对扩展开放,对更改封闭。
  • 类模块应该是可扩展的,但是不可修改。

2.3、单一职责原则(SRP)

  • —个类应该仅有一个引起它变化的原因。·
  • 变化的方向隐含着的责任。

2.4、Liskov替换原则(LSP)

  • 子类必须能够替换它们的基类(IS-A)。
  • 继承表达类型抽象。

2.5、接口隔离原则(ISP)

  • 不应该强迫客户程序依赖它们不用的方法。
  • 接口应该小而完备。

2.6、优先使用对象组合,而不是类继承

  • 类继承通常为“白箱复用”,对象组合通常为“黑箱复用”
  • 继承在某种程度上破坏了封装性,子类父类耦合度高。
  • 而对象组合则只要求被组合的对象具有良好定义的接口,耦合度低。

2.7、封装变化点

  • 使用封装来创建对象之间的分界层,让设计者可以在分界的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。

2.8、针对接口编程,而不是针对实现编程

  • 不将变量类型声明为某个特定的具体类,而是声明为某个接口。
  • 客户程序无需获知对象的具体类型,只需要知道对象所具有的接口。
  • 减少系统中各部分的依赖关系,从而实现“高内聚、低耦合”的类型设计方案。

3、接口标准化

3.1、以史为鉴(1)

  • 秦为什么能够统一六国?
    • 据史书记载和考古发现,秦的兵器不论东西南北,出土地点都有统一的标准
      戈,弩,甚至弩机,弩体,箭头都是一样的.而其他六国则不是.

3.2、以史为鉴(2)

  • 毕升的活字印刷为什么成为四大发明,推动了人类文明的前进?
    • 毕升之前的雕版印刷将字刻死在木板或石板上,每次印刷不同文章,要刻不同的版。而毕升发明的活字印刷首先在板上刻好字格然后再刻单独的字模。印刷时,将活的字模“按需索取”中,不同的排列方法产生不同的文章,而不必重新刻版。

4、将设计原则提升为设计经验

4.1、设计习语Design Idioms

  • Design Idioms 描述与特定编程语言相关的低层模式,技巧,惯用法。

4.2、设计模式Design Patterns

  • Design Patterns主要描述的是“类与相互通信的对象之间的组织关系,包括它们的角色、职责、协作方式等方面。

4.3、架构模式Architectural Patterns

  • Architectural Patterns描述系统中与基本结构组织关系密切的高层模式,包括子系统划分,职责,以及如何组织他们之间的关系原则。

5、模型分类

5.1、GOF-23分类

根据目的来分

  • 创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。GoF 中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。
  • 结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,GoF 中提供了代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。
  • 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。GoF 中提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。

根据作用范围来分

  • 类模式(静态):用于处理类与子类之间的关系,这些关系通过继承来建立,是静态的,在编译时刻便确定下来了。GoF中的工厂方法、(类)适配器、模板方法、解释器属于该模式。
  • 对象模式(动态):用于处理对象之间的关系,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性。GoF 中除了以上 4 种,其他的都是对象模式。

5.2、从封装变化角度对模式分类

  1. 组件协作
  2. 单一职责
  3. 对象创建
  4. 对象性能
  5. 接口隔离
  6. 状态变化
  7. 数据结构
  8. 行为变化
  9. 领域问题

6、重构关键技法

静态
动态
早绑定
晚绑定
继承
组合
编译时依赖
运行时依赖
紧耦合
松耦合

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1093424.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

推荐《咒术回战》

电视动画片《咒术回战》改编自芥见下下著作的同名漫画作品&#xff0c;于2019年11月25日宣布电视动画化的消息 [1] &#xff0c;该系列由MAPPA负责制作。第1期于2020年10月3日—2021年3月27日播出 [8] &#xff0c;全24集。 动画电影《咒术回战 0》于2021年3月27日宣布制作决…

实施 DevSecOps 最佳实践

DevSecOps 是一个框架&#xff0c;它将开发 (Dev)、IT 运营 (Ops) 和安全 (Sec) 流程的实践融合到一个简化的流程中。使用这种方法&#xff0c;DevSecOps 团队能够确保将安全性集成到软件开发生命周期中&#xff0c;确保以“安全第一”的心态构建、部署和维护软件。在本教程中&…

自动驾驶学习笔记(四)——变道绕行仿真

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《2023星火培训【感知专项营】》免费课程—>传送门 文章目录 前言 仿真内容 启动Dreamview 开启Sim…

网络安全(黑客技术)——如何高效自学

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学&#xff1f;如何学&#xff1f; 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c…

ChatGPT AIGC 实现数据分析可视化三维空间展示效果

使用三维空间图展示数据有以下一些好处&#xff1a; 1可视化复杂性&#xff1a;三维图可以展示三个或更多的变量&#xff0c;一眼就能看出数据各维度之间的关系&#xff0c;使复杂数据的理解和分析变得更为直观。 2检测模式和趋势&#xff1a;通过三维图&#xff0c;用户可以…

从零开始的stable diffusion

stable diffusion真的是横空出世&#xff0c;开启了AIGC的元年。不知你是否有和我一样的困惑&#xff0c;这AI工具好像并不是那么听话&#xff1f; 前言 我们该如何才能用好stable diffusion这个工具呢&#xff1f;AI究竟在stable diffusion中承担了什么样的角色&#xff1f;如…

单片机综合小项目

一、单片机做项目常识 1.行业常识 2.方案选型 3.此项目定位和思路 二、单片机的小项目介绍 1.项目名称&#xff1a;基于51单片机的温度报警器 &#xff08;1&#xff09;主控&#xff1a;stc51&#xff1b; &#xff08;2&#xff09;编程语言&#xff1a;C语言 &#xff08;…

数据结构 优先级队列(堆)

数据结构 优先级队列(堆) 文章目录 数据结构 优先级队列(堆)1. 优先级队列1.1 概念 2. 优先级队列的模拟实现2.1 堆的概念2.2 堆的存储方式2.3 堆的创建2.3.1 堆向下调整2.3.2 堆的创建2.3.3 建堆的时间复杂度 2.4 堆的插入与删除2.4.1 堆的插入2.4.2 堆的删除 2.5 用堆模拟实现…

基于微服务+Java+Spring Cloud开发的建筑工地智慧平台源码 云平台多端项目源码

建筑工地智慧平台源码&#xff0c;施工管理端、项目监管端、数据大屏端、移动APP端全套源码 技术架构&#xff1a;微服务JavaSpring Cloud VueUniApp MySql自主版权实际应用案例演示 建筑工地智慧平台已应用于线上巡查、质量管理、实名制管理、危大工程管理、运渣车管理、绿色…

非连续分配管理方式之基本分页存储管理

连续分配&#xff1a;为用户进程分配的必须是一个连续的内存空间。 非连续分配&#xff1a;为用户进程分配的可以是一些分散的内存空间。 基本分页存储管理的思想∶把进程分页&#xff0c;各个页面可离散地放到各个的内存块中。 1.分页存储 1.内存空间分区 将内存空间分为一…

数据库 MySql快速导入外部数据库流程

适用于新安装MySql本地没有数据情况 外部MySql数据库文件 任务管理器停用Mysql进程 将外部文件替换本地默认文件即可 重启电脑导入完成。

MyLife - Docker安装rabbitmq

Docker安装rabbitmq 个人觉得像rabbitmq之类的基础设施在线上环境直接物理机安装使用可能会好些。但是在开发测试环境用docker容器还是比较方便的。这里学习下docker安装rabbitmq使用。 1. rabbitmq 镜像库地址 rabbitmq 镜像库地址&#xff1a;https://hub.docker.com/_/rabbi…

并联谐振DCDC变换器的设计与仿真

摘 要 在我们日常生活中&#xff0c;并联谐振变换器随处可见&#xff0c;因为其相比其他变换器而言结构相对简单&#xff0c;运行稳定且便于维修等优势&#xff0c;最重要的是并联谐振变换器在并网方面具有很好的优势。随着自动控制技术和微电子技术的不断革新&#xff0c;目前…

并联机器人结构分析与领域应用

并联机器人早在20世纪的90年代就已经崭露头角&#xff0c;具有刚度高、速度快、柔性强、重量轻等优点&#xff0c;是工业机器人的新生代力量。并联机器人与串联机器人一起构成了工业机器人的重要部分。在食品、医药、电子等轻工业中应用最为广泛&#xff0c;在物料的搬运、包装…

记录Bug:VScode中无法识别万能头文件#include<bits/stdc++.h>

问题&#xff1a; 在VScode中使用万能头文件#include<bits/stdc.h>编写程序时报错&#xff1a;“检测到 #include 错误。请更新 includePath。已为此翻译单元(D:\Code_C\desC。。。。”。但是普通的c语言头文件#include <stdio.h>等可以正常运行。 原因&#xff1…

Linux网络编程系列之UDP组播

一、什么是UDP组播 UDP组播是指使用用户数据报协议&#xff08;UDP&#xff09;实现的组播方式。组播是一种数据传输方式&#xff0c;允许单一数据包同时传输到多个接收者。在UDP组播中&#xff0c;一个数据包可以被多个接收者同时接收&#xff0c;这样可以降低网络传输的负载和…

P1433 吃奶酪

#include <iostream> #include <cmath> using namespace std; #define M 15 #define S(n) ((n) * (n)) double indx[M 5], indy[M 5], ans 0, sum 0;//坐标数组&#xff0c;从下标为1开始记录 int n, vis[M 5] { 0 };//vis数组&#xff0c;选过的数字标记为1…

N点复序列求2个N点实序列的快速傅里叶变换

一、方法简介 通过一个点复数序列求出两个点实数序列的离散傅里叶变换&#xff0c;进一步提升快速傅里叶变换的效率。 二、方法详解 和是实数序列&#xff0c;且长度都为&#xff0c;定义复数序列&#xff1a; &#xff0c; 则序列和可表示为&#xff1a; 的离散傅…

openssl学习——消息认证码原理

消息认证码原理 消息认证码&#xff08;Message Authentication Code, MAC&#xff09;是一种技术&#xff0c;它的原理是通过对消息和密钥进行特定的处理&#xff0c;生成一个固定长度的数据&#xff0c;这个数据就是消息认证码&#xff08;MAC&#xff09;。这个过程可以看作…

【10】基础知识:React - DOM的diffing算法

一、虚拟 DOM 中 key 的作用 react/vue 中的 key 有什么作用&#xff1f;key的内部原理是什么&#xff1f; 简单来说&#xff1a; key 是虚拟 DOM 对象的标识&#xff0c;在更新显示时 key 起着极其重要的作用&#xff0c;提高渲染效率&#xff0c;防止渲染错误。 详细的说…