设计模式基础知识-总结

一、面向对象编程

2.1 概述

简称Object Oriented Program(OOP), 指以类或对象 作为基础组织单元 , 遵循封装,继承,多态以及抽象等特性,进行编程。其中面向对象不一定遵循封装、继承以及多态等, 封装和继承等特性,只是前人总结的套路规范,遵循该套规范,可以快速,准确以及优雅的完成面向对象编程。

2.2 基本思想

软件系统设计的三个阶段:分析、设计以及实现。在面向对象领域,对应着面向对象设计(OOA),面向对象设计(OOD)以及面向对象编程(OOP).其中OOA和OOD解决了以下具体问题:被分为哪些类,类的属性和行为以及类与类之间的组织【交互关系】。整体来看:OOA:做什么 OOD:怎么做 OOP:将分析和设计翻译为代码的过程

2.3 四大特性详解

2.3.1 封装

本质上就是访问权限控制,哪些内容是允许访问的,哪些是不允许访问的, 防止权限的滥用。存在的意义:

  • 保护数据不被随意滥用, 提高代码的可维护性
  • 通过暴露有限的行为, 提高代码的易用性

2.3.2 继承

对现实世界的直接映射,便于理解, 提高代码的复用性。但要注意继承的层级, 层级过深,会降低代码的可读性。

2.3.3 抽象

隐藏方法的具体实现 。从调用方角度来看, 并不关心方法是怎么实现的, 只需告诉该方法能做什么即可。类比到现实世界, 买车的时候,仅关注车提供的功能,并不关注你是怎么做出来的. 本质就是复杂世界或复杂系统提供的信息太多了,有些信息是完全没必要关注的,因此,仅关注你所关心的即可。

实现方式: Java中提供了接口和抽象语法

存在意义:提高代码可扩展性,可读性和可维护性; 是处理复杂系统的有效手段。

2.3.4 多态

指子类可以灵活替换父类,需要编程语言特殊语言支持。类似于Java的接口、抽象类等。

存在意义:提高代码的可扩展性, 可复用性,是设计模式的基础。可复用指的是如果不采用多态的方式, 相同的代码可能需要使用多份。

2.4 常见的面向对象写为面向过程的示例

2.4.1 getter和setter方法的滥用

上面说了,面向对象是通过访问权限控制,隐藏内部数据,仅提供有限的接口给外部使用。但是普通对象 的getter和setter方法滥用,就会导致对象中虽然定义属性是private,但实际上是public的操作权限。若类中存在容器对象, 即使只提供getter方法,也可以修改容器中的数据,推荐做法为:

java 复制代码
public List<ShoppingCartItem> getItems() {
    return Collections.unmodifiableList(this.items);
}

2.4.2 全局变量和全局方法的滥用

一般项目中,会写一个大而全的Constants常量类,明显违背了面向对象设计,存在以下缺点:

  1. 影响代码的可维护性。由于这个类是全局的,许多开发人员都会修改,提交冲突概率增大,同时查找比较耗时;
  2. 增加代码的编译时间。这个类全局的,很多地方都会被用到,一旦constants类发生变化,许多依赖它的类都会重新进行编译,非常耗时;
  3. 影响代码的复用性。若某个第三方组件依赖项目中的某一类,而这个类又依赖constants类,导致大量无关的常量被引入进来。

推荐做法:尽量做大职责单一,按照业务的不同,划分不同xxxcConstants类

2.4.3 定义数据和方法相分离的类

就是经常使用的MVC模式,dao层的实体类和service服务类相分离,即基于贫血模型的开发方法。

2.4.4 底层思维过程

现实中,为了完成一个任务,一般会思考,先做什么,后做什么,如何一步步完成任务,这就是典型的面向过程,适合简单系统 开发,例如MVC开发模式。而面向对象是自底向上 的逻辑,先构建每个任务的模块,然后思考设计类与类之间的交互,最后按照流程组装起来完成任务,适合复杂系统的开发。

二、接口vs抽象类的区别

2.1 定义

  • 接口:指的是定义一组协议或规范。接口通常只定义方法的声明,不做具体的实现; 接口不能创建对象;实现接口时,必须实现所有的方法
  • 抽象类:是对成员变量和方法的抽象。抽象类不允许被实例化;抽象类可以包含属性和方法;子类必须实现抽象类的所有抽象方法

2.2 解决问题类型

2.2.1 接口

主要解决的是has-a问题, 降低代码之间的耦合性, 将接口和实现相分离, 提高代码的扩展性。接口代表自上而下的设计思路。

2.2.2 抽象类

主要解决的是is-a问题,提高代码的复用性。抽象类代表自下而上的设计思路。

为什么不直接使用普通类的 ?原因在于:抽象类的抽象方法强制 开发人员必须实现,而普通类则没有要求,那么可能会造成某些方法应该被实现,却没有被实现,不利于代码的可读性,同时无法使用多态特性

2.3 实际使用场景

若要表示is-a关系, 且为了提高代码的复用性, 则使用抽象类; 若要表示has-a关系, 且为了提高代码的扩展性, 则使用接口;

三、基于接口而非实现编程的讨论

概述:基于接口而非实现编程,又称基于抽象而非实现编程,将接口和实现相分离,隐藏不稳定的实现,暴露稳定的接口实现解耦,增加代码的可扩展性。

实现步骤

  1. 接口函数的命名要抽象。反例:uploadAliyun(), 正例:upload()
  2. 暴露通用【统一】的方法。
  3. 封装具体实现细节

什么场景下使用该原则? 该条原则设计的初衷是面对未来变化的场景。若某个业务场景的实现只有一种方式,就没必要设计接口; 否则,就需要设计接口。

四、组合和继承的讨论

继承虽然可以提高代码的可复用性 ,但存在继承层次过深 ,导致代码难维护 的问题。 可以通过组合,接口和委托三个技术手段来解决。适用场景:

  1. 若类之间的继承结构稳定,且继承层次比较浅(最多有两层),继承关系不复杂,考虑使用继承;
  2. 否则,尽量使用组合来替代继承。 举个例子:A类和B类之间没有继承关系,但是都用到了URL拼接和分割的功能。若为了代码复用,抽出一个父类,会影响代码的可读性,此时使用组合则更加合理,更加灵活。

注意:上述总结来自于# 设计模式之美------王争

相关推荐
摇滚侠11 小时前
Spring Boot 3零基础教程,IOC容器中组件的注册,笔记08
spring boot·笔记·后端
程序员小凯13 小时前
Spring Boot测试框架详解
java·spring boot·后端
你的人类朋友14 小时前
什么是断言?
前端·后端·安全
程序员小凯15 小时前
Spring Boot缓存机制详解
spring boot·后端·缓存
i学长的猫15 小时前
Ruby on Rails 从0 开始入门到进阶到高级 - 10分钟速通版
后端·ruby on rails·ruby
用户214118326360216 小时前
别再为 Claude 付费!Codex + 免费模型 + cc-switch,多场景 AI 编程全搞定
后端
茯苓gao16 小时前
Django网站开发记录(一)配置Mniconda,Python虚拟环境,配置Django
后端·python·django
Cherry Zack16 小时前
Django视图进阶:快捷函数、装饰器与请求响应
后端·python·django
爱读源码的大都督17 小时前
为什么有了HTTP,还需要gPRC?
java·后端·架构
码事漫谈17 小时前
致软件新手的第一个项目指南:阶段、文档与破局之道
后端