01.面向对象设计思想

01.面向对象设计思想

目录介绍
  • 01.看一个演变案例
    • 1.1 一个案例介绍
    • 1.2 普通过程思维
    • 1.3 使用面向对象
    • 1.4 案例对比分析
  • 02.面向对象的思想
    • 2.1 面向过程思想
    • 2.2 面向过程演变
    • 2.3 面向对象思想
    • 2.4 面向对象思想特点
  • 03.面向对象编程
    • 3.1 基础概念
    • 3.2 编程语言划分
    • 3.3 面向对象分析和设计
    • 3.4 UML介绍说明
  • 04.面向对象和过程
    • 4.1 背景介绍说明
    • 4.2 思考几个问题
    • 4.3 面向过程编程
    • 4.4 面向过程局限性
    • 4.5 使用场景分析
    • 4.6 案例分析总结
    • 4.7 总结和梳理

01.看一个演变案例

1.1 一个案例介绍

面向过程面向对象 是两种不同的编程范式。通过一个通俗的案例,可以清晰地展示它们的区别。以下是一个简单的例子:计算矩形的面积和周长

1.2 普通过程思维

不使用面向对象(面向过程),在面向过程的编程中,代码通常以函数为中心,数据和操作是分离的。

java 复制代码
public class RectangleWithoutOOP {
    public static void main(String[] args) {
        // 定义矩形的长和宽
        double length = 5.0;
        double width = 3.0;

        // 计算面积
        double area = calculateArea(length, width);
        System.out.println("面积: " + area);

        // 计算周长
        double perimeter = calculatePerimeter(length, width);
        System.out.println("周长: " + perimeter);
    }

    // 计算面积的函数
    public static double calculateArea(double length, double width) {
        return length * width;
    }

    // 计算周长的函数
    public static double calculatePerimeter(double length, double width) {
        return 2 * (length + width);
    }
}

特点

  • 数据和操作是分离的。
  • 代码逻辑集中在函数中。
  • 如果需要对多个矩形进行操作,需要重复定义变量和调用函数。

1.3 使用面向对象

使用面向对象,在面向对象的编程中,代码以对象为中心,数据和操作被封装在类中。

java 复制代码
// 定义一个矩形类
class Rectangle {
    // 属性:长和宽
    private double length;
    private double width;

    // 构造方法:初始化长和宽
    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }

    // 方法:计算面积
    public double calculateArea() {
        return length * width;
    }

    // 方法:计算周长
    public double calculatePerimeter() {
        return 2 * (length + width);
    }
}

public class RectangleWithOOP {
    public static void main(String[] args) {
        // 创建一个矩形对象
        Rectangle rectangle = new Rectangle(5.0, 3.0);

        // 调用对象的方法计算面积和周长
        System.out.println("面积: " + rectangle.calculateArea());
        System.out.println("周长: " + rectangle.calculatePerimeter());
    }
}

特点

  • 数据和操作被封装在 Rectangle 类中。
  • 通过创建对象来操作数据。
  • 代码更易于扩展和维护。例如,如果需要添加新的功能(如判断是否为正方形),只需在 Rectangle 类中添加方法即可。

1.4 案例对比分析

对比分析

特性 面向过程 面向对象
代码组织 以函数为中心,数据和操作分离 以对象为中心,数据和操作封装在类中
可扩展性 扩展时需要修改函数或添加新函数 扩展时只需添加新的方法或类
可维护性 代码逻辑分散,维护较困难 代码逻辑集中,易于维护
复用性 复用性较低,需要重复定义变量和调用函数 复用性高,通过创建对象即可复用功能
适合场景 简单、一次性任务 复杂、需要长期维护的项目
思维习惯 面向过程的编程方式更接近计算机的执行方式 人类更倾向于以"对象"和"行为"来理解问题,而不是一系列的过程和步骤

02.面向对象的思想

2.1 面向过程思想

我们来回想一下,这几天我们完成一个需求的步骤:首先是搞清楚我们要做什么,然后在分析怎么做,最后我们再代码体现。

举个简单的例子:相信大家都被问过这样一个问题: 把大象装入冰箱需要几步?按照面向过程的思想,需要三步:

  1. 第一步:打开冰箱
  2. 第二步:把大象塞进去
  3. 第三步:关上冰箱

一步一步去实现,而具体的每一步都需要我们去实现和操作。这些步骤相互调用和协作,完成我们的需求。

在上面的每一个具体步骤中我们都是参与者,并且需要面对具体的每一个步骤和过程,这就是面向过程最直接的体现。

那么什么是面向过程开发呢? 面向过程开发,其实就是面向着具体的每一个步骤和过程,把每一个步骤和过程完成,然后由这些功能方法相互调用,完成需求

2.2 面向过程演变

当需求单一,或者简单时,我们一步一步去操作没问题,并且效率也挺高。

可随着需求的更改,功能的增多,发现需要面对每一个步骤很麻烦了。这时就开始思索,

能不能把这些步骤和功能在进行封装,封装时根据不同的功能,进行不同的封装,功能类似的封装在一起。

这样结构就清晰了很多。用的时候,找到对应的类就可以了。这就是面向对象的思想。

2.3 面向对象思想

面向对象:就是把现实中的事物都抽象为"对象"。每个对象是唯一的,且都可以拥有它的属性与行为。我们就可以通过调用这些对象的方法、属性去解决问题。

在这个例子中:我们可以把大象看作一个对象,冰箱看作一个对象。冰箱的一些功能:开门、装物体、关门

面向对象对象的特点:有很好的延展性,比如我给大象赋予了一个吃的功能,它通过调用就可以在冰箱里去吃东西。面向对象就是把现实问题抽象为对象,通过调用每个对象的属性或功能去解决问题。

2.4 面向对象思想特点

  • a:是一种更符合我们思想习惯的思想
  • b:可以将复杂的事情简单化
  • c:将我们从执行者变成了指挥者。角色发生了转换

03.面向对象编程

3.1 基础概念

面向对象编程中有两个非常重要、非常基础的概念,那就是 类(class)和对象(object)

直到今天,如果不按照严格的定义来说,大部分编程语言都是面向对象编程语言,比如 Java、C++、Go、Python、C#、Ruby、JavaScript、Objective-C、Scala、PHP、Perl 等等。

大部分程序员在开发项目的时候,都是基于面向对象编程语言进行的面向对象编程。

面向对象编程和面向对象编程语言。那究竟什么是面向对象编程?什么语言才算是面向对象编程语言呢?

  1. 面向对象编程:是一种编程范式或编程风格。它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石

  2. 面向对象编程语言:是支持类或对象的语法机制,并有现成的语法机制,能方便地实现面向对象编程四大特性(封装、抽象、继承、多态)的编程语言。

3.2 编程语言划分

"如果不按照严格的定义来说,大部分编程语言都是面向对象编程语言"。为什么要加上"如果不按照严格的定义"这个前提呢?那是因为,如果按照刚刚我们给出的严格的面向对象编程语言的定义,前面提到的有些编程语言,并不是严格意义上的面向对象编程语言。

比如 JavaScript,它不支持封装和继承特性,按照严格的定义,它不算是面向对象编程语言,但在某种意义上,它又可以算得上是一种面向对象编程语言。为什么这么说呢?

面向对象编程从字面上,按照最简单、最原始的方式来理解,就是将对象或类作为代码组织的基本单元,来进行编程的一种编程范式或者编程风格。并不一定需要封装、抽象、继承、多态这四大特性的支持。

但是,在进行面向对象编程的过程中,人们不停地总结发现,有了这四大特性,我们就能更容易地实现各种面向对象的代码设计思路。

比如,我们在面向对象编程的过程中,经常会遇到 is-a 这种类关系(比如狗是一种动物),而继承这个特性就能很好地支持这种 is-a 的代码设计思路,并且解决代码复用的问题,所以,继承就成了面向对象编程的四大特性之一。

但是随着编程语言的不断迭代、演化,人们发现继承这种特性容易造成层次不清、代码混乱,所以,很多编程语言在设计的时候就开始摒弃继承特性,比如 Go 语言。

3.3 面向对象分析和设计

跟面向对象编程经常放到一块儿来讲的还有另外两个概念,那就是面向对象分析(OOA)和面向对象设计(OOD)。

  1. 面向对象分析英文缩写是 OOA,全称是 Object Oriented Analysis;
  2. 面向对象设计的英文缩写是 OOD,全称是 Object Oriented Design。
  3. OOA、OOD、OOP 三个连在一起就是面向对象分析、设计、编程(实现),正好是面向对象软件开发要经历的三个阶段。

什么是面向对象分析和设计。这两个概念相对来说要简单一些。

面向对象分析与设计中的"分析"和"设计"这两个词,我们完全可以从字面上去理解,不需要过度解读,简单类比软件开发中的需求分析、系统设计即可。

面向对象分析就是要搞清楚做什么,面向对象设计就是要搞清楚怎么做。两个阶段最终的产出是类的设计,包括程序被拆解为哪些类,每个类有哪些属性方法、类与类之间如何交互等等。

不过,你可能会说,那为啥前面还加了个修饰词"面向对象"呢?有什么特殊的意义吗?

在前面加"面向对象"这几个字,是因为我们是围绕着对象或类来做需求分析和设计的。更多博客。

分析和设计两个阶段最终的产出是类的设计,包括程序被拆解为哪些类,每个类有哪些属性方法,类与类之间如何交互等等。它们比其他的分析和设计更加具体、更加落地、更加贴近编码,更能够顺利地过渡到面向对象编程环节。这也是面向对象分析和设计,与其他分析和设计最大的不同点。

面向对象分析、设计、编程到底都负责做哪些工作呢?简单点讲,面向对象分析就是要搞清楚做什么,面向对象设计就是要搞清楚怎么做,面向对象编程就是将分析和设计的的结果翻译成代码的过程

3.4 UML介绍说明

什么是 UML?我们是否需要 UML?面向对象分析、设计、编程,我们就不得不提到另外一个概念,那就是 UML(Unified Model Language),统一建模语言。

很多讲解面向对象或设计模式的书籍,常用它来画图表达面向对象或设计模式的设计思路。

实际上,UML 是一种非常复杂的东西。它不仅仅包含我们常提到类图,还有用例图、顺序图、活动图、状态图、组件图等。即便仅仅使用类图,学习成本也是很高的。就单说类之间的关系,UML 就定义了很多种,比如泛化、实现、关联、聚合、组合、依赖等。

要想完全掌握,并且熟练运用这些类之间的关系,来画 UML 类图,肯定要花很多的学习精力。而且,UML 作为一种沟通工具,即便你能完全按照 UML 规范来画类图,可对于不熟悉的人来说,看懂的成本也还是很高的。

04.面向对象和过程

4.1 背景介绍说明

实际上,除了面向对象之外,被大家熟知的编程范式还有另外两种,面向过程编程和函数式编程。面向过程这种编程范式随着面向对象的出现,已经慢慢退出了舞台,而函数式编程目前还没有被广泛接受。

很多人搞不清楚面向对象和面向过程的区别,总以为使用面向对象编程语言来做开发,就是在进行面向对象编程了。而实际上,他们只是在用面向对象编程语言,编写面向过程风格的代码而已,并没有发挥面向对象编程的优势。

4.2 思考几个问题

详细对比一下面向过程和面向对象这两种编程范式,带你一块搞清楚下面这几个问题:

  1. 什么是面向过程编程与面向过程编程语言?
  2. 面向对象编程相比面向过程编程有哪些优势?
  3. 为什么说面向对象编程语言比面向过程编程语言更高级?
  4. 有哪些看似是面向对象实际是面向过程风格的代码?
  5. 在面向对象编程中,为什么容易写出面向过程风格的代码?
  6. 面向过程编程和面向过程编程语言就真的无用武之地了吗?

4.3 面向过程编程

面向对象编程语言是支持类或对象的语法机制,并有现成的语法机制,能方便地实现面向对象编程四大特性(封装、抽象、继承、多态)的编程语言。

类比面向对象编程与面向对象编程语言的定义,对于面向过程编程和面向过程编程语言这两个概念,我给出下面这样的定义。

面向过程编程也是一种编程范式或编程风格。它以过程(可以为理解方法、函数、操作)作为组织代码的基本单元,以数据(可以理解为成员变量、属性)与方法相分离为最主要的特点。面向过程风格是一种流程化的编程风格,通过拼接一组顺序执行的方法来操作数据完成一项功能。

面向过程编程语言首先是一种编程语言。它最大的特点是不支持类和对象两个语法概念,不支持丰富的面向对象编程特性(比如继承、多态、封装),仅支持面向过程编程。

4.4 面向过程局限性

这里给出的面向过程编程和面向过程编程语言的定义,也并不是严格的官方定义。之所以要给出这样的定义,只是为了跟面向对象编程及面向对象编程语言做个对比,以方便你理解它们的区别。

用一个例子进一步解释一下。假设我们有一个记录了用户信息的文本文件 users.txt,每行文本的格式是 name&age&gender(比如,小王 & 28 & 男)。我们希望写一个程序,从 users.txt 文件中逐行读取用户信息,然后格式化成 name\tage\tgender(其中,\t 是分隔符)这种文本格式,并且按照 age 从小到达排序之后,重新写入到另一个文本文件 formatted_users.txt 中。

针对这样一个程序的开发,我们一块来看看,用面向过程和面向对象两种编程风格,编写出来的代码有什么不同。

先来看,用面向过程这种编程风格写出来的代码是什么样子的。注意,下面的代码是用 C 语言这种面向过程的编程语言来编写的。

c 复制代码
struct User {
  char name[64];
  int age;
  char gender[16];
};

struct User parse_to_user(char* text) {
  // 将text("小王&28&男")解析成结构体struct User
}

char* format_to_text(struct User user) {
  // 将结构体struct User格式化成文本("小王\t28\t男")
}

void sort_users_by_age(struct User users[]) {
  // 按照年龄从小到大排序users
}

void format_user_file(char* origin_file_path, char* new_file_path) {
  // open files...
  struct User users[1024]; // 假设最大1024个用户
  int count = 0;
  while(1) { // read until the file is empty
    struct User user = parse_to_user(line);
    users[count++] = user;
  }
  
  sort_users_by_age(users);
  
  for (int i = 0; i < count; ++i) {
    char* formatted_user_text = format_to_text(users[i]);
    // write to new file...
  }
  // close files...
}

int main(char** args, int argv) {
  format_user_file("/home/zheng/user.txt", "/home/zheng/formatted_users.txt");
}

再来看,用面向对象这种编程风格写出来的代码是什么样子的。注意,下面的代码是用 Java 这种面向对象的编程语言来编写的。

java 复制代码
public class User {
  private String name;
  private int age;
  private String gender;
  
  public User(String name, int age, String gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
  }
  
  public static User praseFrom(String userInfoText) {
    // 将text("小王&28&男")解析成类User
  }
  
  public String formatToText() {
    // 将类User格式化成文本("小王\t28\t男")
  }
}

public class UserFileFormatter {
  public void format(String userFile, String formattedUserFile) {
    // Open files...
    List users = new ArrayList<>();
    while (1) { // read until file is empty 
      // read from file into userText...
      User user = User.parseFrom(userText);
      users.add(user);
    }
    // sort users by age...
    for (int i = 0; i < users.size(); ++i) {
      String formattedUserText = user.formatToText();
      // write to new file...
    }
    // close files...
  }
}

public class MainApplication {
  public static void main(Sring[] args) {
    UserFileFormatter userFileFormatter = new UserFileFormatter();
    userFileFormatter.format("/home/zheng/users.txt", "/home/zheng/formatted_users.txt");
  }
}

从上面的代码中,我们可以看出,面向过程和面向对象最基本的区别就是,代码的组织方式不同。面向过程风格的代码被组织成了一组方法集合及其数据结构(struct User),方法和数据结构的定义是分开的。面向对象风格的代码被组织成一组类,方法和数据结构被绑定一起,定义在类中。

两种编程风格实现的代码貌似差不多啊,顶多就是代码的组织方式有点区别,没有感觉到面向对象编程有什么明显的优势呀!你的感觉没错。之所以有这种感觉,主要原因是这个例子程序比较简单、不够复杂。

4.5 使用场景分析

面向过程的使用场景:整个程序的处理流程只有一条主线,很容易被划分成顺序执行的几个步骤,然后逐句翻译成代码,这就非常适合采用面向过程这种面条式的编程风格来实现。

但对于大规模复杂程序的开发来说,整个程序的处理流程错综复杂,并非只有一条主线。

如果把整个程序的处理流程画出来的话,会是一个网状结构。如果我们再用面向过程编程这种流程化、线性的思维方式,去翻译这个网状结构,去思考如何把程序拆解为一组顺序执行的方法,就会比较吃力。这个时候,面向对象的编程风格的优势就比较明显了。

4.6 案例分析总结

面向对象编程是以类为思考对象。在进行面向对象编程的时候,我们并不是一上来就去思考,如何将复杂的流程拆解为一个一个方法,而是采用曲线救国的策略,先去思考如何给业务建模,如何将需求翻译为类,如何给类之间建立交互关系,而完成这些工作完全不需要考虑错综复杂的处理流程。

当我们有了类的设计之后,然后再像搭积木一样,按照处理流程,将类组装起来形成整个程序。这种开发模式、思考问题的方式,能让我们在应对复杂程序开发的时候,思路更加清晰。

除此之外,面向对象编程还提供了一种更加清晰的、更加模块化的代码组织方式。比如,我们开发一个电商交易系统,业务逻辑复杂,代码量很大,可能要定义数百个函数、数百个数据结构,那如何分门别类地组织这些函数和数据结构,才能不至于看起来比较凌乱呢?类就是一种非常好的组织这些函数和数据结构的方式,是一种将代码模块化的有效手段。

你可能会说,像 C 语言这种面向过程的编程语言,我们也可以按照功能的不同,把函数和数据结构放到不同的文件里,以达到给函数和数据结构分类的目的,照样可以实现代码的模块化。你说得没错。只不过面向对象编程本身提供了类的概念,强制你做这件事情,而面向过程编程并不强求。这也算是面向对象编程相对于面向过程编程的一个微创新吧。

实际上,利用面向过程的编程语言照样可以写出面向对象风格的代码,只不过可能会比用面向对象编程语言来写面向对象风格的代码,付出的代价要高一些。而且,面向过程编程和面向对象编程并非完全对立的。很多软件开发中,尽管利用的是面向过程的编程语言,也都有借鉴面向对象编程的一些优点。

4.7 总结和梳理

一起总结回顾一下,你需要重点掌握的几个概念和知识点。

1.什么是面向对象编程?面向对象编程是一种编程范式或编程风格。它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石 。

2.什么是面向对象编程语言?面向对象编程语言是支持类或对象的语法机制,并有现成的语法机制,能方便地实现面向对象编程四大特性(封装、抽象、继承、多态)的编程语言。

3.如何判定一个编程语言是否是面向对象编程语言?如果按照严格的的定义,需要有现成的语法支持类、对象、四大特性才能叫作面向对象编程语言。如果放宽要求的话,只要某种编程语言支持类、对象语法机制,那基本上就可以说这种编程语言是面向对象编程语言了,不一定非得要求具有所有的四大特性。

4.面向对象编程和面向对象编程语言之间有何关系?面向对象编程一般使用面向对象编程语言来进行,但是,不用面向对象编程语言,我们照样可以进行面向对象编程。反过来讲,即便我们使用面向对象编程语言,写出来的代码也不一定是面向对象编程风格的,也有可能是面向过程编程风格的。

5.什么是面向对象分析和面向对象设计?简单点讲,面向对象分析就是要搞清楚做什么,面向对象设计就是要搞清楚怎么做。两个阶段最终的产出是类的设计,包括程序被拆解为哪些类,每个类有哪些属性方法、类与类之间如何交互等等。

面向对象编程相比面向过程编程有哪些优势?面向对象编程相比起面向过程编程的优势主要有三个。

  1. 对于大规模复杂程序的开发,程序的处理流程并非单一的一条主线,而是错综复杂的网状结构。面向对象编程比起面向过程编程,更能应对这种复杂类型的程序开发。
  2. 面向对象编程相比面向过程编程,具有更加丰富的特性(封装、抽象、继承、多态)。利用这些特性编写出来的代码,更加易扩展、易复用、易维护。
  3. 从编程语言跟机器打交道的方式的演进规律中,我们可以总结出:面向对象编程语言比起面向过程编程语言,更加人性化、更加高级、更加智能。

05.更多内容推荐

模块 描述 备注
GitHub 多个YC系列开源项目,包含Android组件库,以及多个案例 GitHub
博客汇总 汇聚Java,Android,C/C++,网络协议,算法,编程总结等 YCBlogs
设计模式 六大设计原则,23种设计模式,设计模式案例,面向对象思想 设计模式
Java进阶 数据设计和原理,面向对象核心思想,IO,异常,线程和并发,JVM Java高级
网络协议 网络实际案例,网络原理和分层,Https,网络请求,故障排查 网络协议
计算机原理 计算机组成结构,框架,存储器,CPU设计,内存设计,指令编程原理,异常处理机制,IO操作和原理 计算机基础
学习C编程 C语言入门级别系统全面的学习教程,学习三到四个综合案例 C编程
C++编程 C++语言入门级别系统全面的教学教程,并发编程,核心原理 C++编程
算法实践 专栏,数组,链表,栈,队列,树,哈希,递归,查找,排序等 Leetcode
Android 基础入门,开源库解读,性能优化,Framework,方案设计 Android

23种设计模式

23种设计模式 & 描述 & 核心作用 包括
创建型模式 提供创建对象用例。能够将软件模块中对象的创建和对象的使用分离 工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern)
结构型模式 关注类和对象的组合。描述如何将类或者对象结合在一起形成更大的结构 适配器模式(Adapter Pattern) 桥接模式(Bridge Pattern) 过滤器模式(Filter、Criteria Pattern) 组合模式(Composite Pattern) 装饰器模式(Decorator Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern)
行为型模式 特别关注对象之间的通信。主要解决的就是"类或对象之间的交互"问题 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 访问者模式(Visitor Pattern)
相关推荐
追逐时光者2 小时前
推荐 7 款开源、免费、美观的 .NET Blazor UI 组件库
后端·.net
叫我:松哥2 小时前
基于python django深度学习的中文文本检测+识别,可以前端上传图片和后台管理图片
图像处理·人工智能·后端·python·深度学习·数据挖掘·django
程序员岳焱2 小时前
从 0 到 1:Spring Boot 与 Spring AI 打造智能客服系统(基于DeepSeek)
人工智能·后端·deepseek
mldong2 小时前
GoFrame中间件注册竟然还能这样玩?团队开发效率提升200%!
后端·架构·go
艾醒3 小时前
使用服务器训练模型详解
后端
别来无恙1493 小时前
Spring Boot自动装配原理深度解析:从核心注解到实现机制
java·spring boot·后端
愿你天黑有灯下雨有伞4 小时前
Spring Boot+Redis Zset:三步构建高可靠延迟队列系统
spring boot·redis·后端
bobz9654 小时前
交换机上的DMZ的优先级比ACL的限制的优先级更高么
后端
你我约定有三4 小时前
RabbitMQ--批量处理
java·windows·后端·rabbitmq
码事漫谈5 小时前
DDD领域驱动设计C++实现案例:订单管理系统
后端