设计模式基础知识-总结

一、面向对象编程

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拼接和分割的功能。若为了代码复用,抽出一个父类,会影响代码的可读性,此时使用组合则更加合理,更加灵活。

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

相关推荐
谦行1 小时前
前端视角 Java Web 入门手册 4.4:Web 开发基础—— Listener
java·后端
非优秀程序员1 小时前
使用Python给自己网站生成llms.txt
人工智能·后端·架构
尘鹄1 小时前
一文讲懂Go语言如何使用配置文件连接数据库
开发语言·数据库·后端·golang
benben0442 小时前
Django小白级开发入门
后端·python·django
qw9492 小时前
SpringBoot3—场景整合:环境准备
java·后端
孟and平4 小时前
Flask 打包为exe 文件
后端·python·flask
大只因bug6 小时前
基于Django的协同过滤算法养老新闻推荐系统的设计与实现
后端·python·django·协同过滤算法推荐系统·新闻推荐网站系统·养老新闻推荐系统·个性化新闻推荐网站系统
_TokaiTeio10 小时前
JVM面试题100
java·开发语言·jvm·后端·虚拟机
计算机-秋大田10 小时前
基于Spring Boot的健美操评分管理系统设计与实现(LW+源码+讲解)
java·spring boot·后端
格子先生Lab10 小时前
Spring Boot 本地缓存工具类设计与实现
spring boot·后端·缓存