>[success]
> **所谓的抽象,就是将一系列事物共有的特质提取出来,舍去独有的部分的过程**
> **也可以说是指从具体问题中,提取出具有共性的模式,再使用通用的解决方法加以处理**
## 通俗的理解抽象
大家从小到大学到的大部分知识,无一例外的都是将具体事物抽象出来的结果
例如大家学到的 1+1 = 2 这个概念,如何理解和抽象的关系?
一只鸡加一只鸡等于两只鸡,一只狗加一只狗就是两只狗
**这个过程中,共有的特质就是一个实体加另一个实体,就等于了两个实体,独有特质就是一个是猫,一个是狗。**
于是加法了概念就这样诞生,在你理解了这个概念后,就可以灵活应用,比如你就会知道一个人加一个人就等于两个人
而学习知识最好的办法就是将抽象的知识类比为具体的事物来学习,比如老师教你们1+1 = 2 这个概念,是不是就是举的例子,一只鸡加一只鸡等于两只鸡这样?
**而我们在应用学习到的知识时候,也是这个道理,先将具体问题抽象为我们所储备的知识,再用知识去解决问题**
一个车可以座5人,10个车能做几人?我们要解决这个问题,得先把问题转为我们学过的数学乘法,在计算出结果
## 抽象和编程的关系
看到这里你应该对抽象有了一定的理解,那么抽象和编程有什么关系?
>[success]
> 一个软件的架构写的如何,包括拓展性,可维护性,可移植性等等方面几乎直接由程序开发者对事物的抽象能力来决定,他们能根据项目的需要总结出什么地方需要用什么算法,什么数据结构,什么设计模式等等。
> 大家所熟知的各类设计模式,数据结构,算法,就是对各种情况抽象出来的结果。
所以各位应该知道为什么学习这些知识如此重要。
>[success]
>
> Thinkphp框架的源码就是不错的典范,不少朋友说是仿的 laravel,这里抛开框架整体思想不说,仅讨论代码的规范和各种设计思想,十分是值得大家学习
**为什么要抽象**
> 代码可复用性强,表现为同样的功能,绝不写第二次,没有重复功能的代码 参考 Thinkphp源码里 `think\File `类的 `getInfo `方法,写好后其他地方只管调用即可
> 代码可移植性强,写好的功能可以把代码提出来拿到其他项目里用,没有耦合(关于耦合的概念看文档的‘耦合于解耦’篇)参考Thinkphp源码里的` vender\topthink\think-image`能,使用composer安装,即便拿到其他框架一样可以工作,不会依赖 Thinkphp源码里的任何类库或者函数
**抽象的原则及如何抽象**
抽象需要对计算过程进行观察,看哪些计算模式是固定的,哪些是经常变化的,将共有的部分提取出来封装。
> 通常在抽象时需要遵循一个‘**三次原则**’
通俗的说,在编写项目过程中,当一个重复的功能出现在三次以上的地方时候,就应该考虑将共有的部分封装为函数或者类,在需要用到的地方调用,不同的部分用传参数的方式传进去
> 第一次用到某个功能时,你写一个特定的解决方法;
> 第二次又用到的时候,你拷贝上一次的代码;
> 第三次出现的时候,你才着手"抽象化",写出通用的解决方法。
### 理由
> (1)省事。如果一种功能只有一到两个地方会用到,就不需要在"抽象化"上面耗费时间了。
> (2)容易发现模式。"抽象化"需要找到问题的模式,问题出现的场合越多,就越容易看出模式,从而可以更准确地"抽象化"。
> (3)防止过度冗余。如果一种功能同时有多个实现,管理起来非常麻烦,修改的时候需要修改多处。在实际工作中,重复实现最多可以容忍出现一次,再多就无法接受了。
>[warning]
> 当然,面对一些能预知的通用功能,应该先封装好,在进行封装,后面在调用,比如类似排序函数之类的功能等
**通常封装的形式粒度由小到大**
> 1. **函数和类中的方法** : 参考thinkphp源码里 `helper.php` 里的函数
> 2. **类** : 包括工具类,机制类等等,参考thinkphp源码里 thinkphp 命名空间下的各个类文件,session,url等等
> 3. **类库** : 功能比较庞大,一个类封装不了的时候,可以考虑封装为多个类,各司其职,相互调用完成复杂逻辑,类似phpexcel,phpMail这样大型工具库,可以参考thinkphp源码里` think\cache` 文件夹下的各个类
>[success]
> 经验丰富的程序设计者,总是可以判断出做出什么程度的抽象是合适的
**面向对象中的抽象类 abstract**
如何理解面向对象中的抽象类(abstract)
参考thinkphp源码里` think\cache` 文件夹下的各个类文件
你会发现有个Driver.php里面有个`abstract class Driver`,有好几个方法如` has,get,set`等都是没有方法体,前面用了 `abstract`修饰。再看`driver`文件夹下有很多文件,这些类文件继承了`Driver`,他们每个类都重写了`Driver`类里的用`abstract`修饰过的方法,在这里就是对缓存这个动作做了抽象的结果。
>[success]
> **共有特质**:不论用何种方式缓存,`File,Memcache,Redis`等等,必然都有个`set,get,clear`等一些方法
> **独有特质**:每个方式写入数据的方式都不一样,参考每个继承了`Driver`的类,如`File,Memcache`等,他们重写的方法体里就是具体的逻辑
>
>[success]
> **另外,这个设计思想是典型的适配器模式
> 同样的示例参考 `namespace think\db\connector` 下各个类文件和 `namespace think\db `下的`Connection`类之间的关系**
- 序言
- 图片预览
- 诠释高效开发
- 提问的智慧
- GIT命令参考
- 安装composer
- 断点调试技巧
- 调试环境的搭建
- 调试工具的使用及技巧
- 前置基础-TP底层讲解
- 理解编程的抽象
- 耦合与解耦
- 自动加载
- 反射类
- 控制反转(IOC)和依赖注入(DI)
- iThink 自定义依赖注入的实现
- 常用设计模式
- SPL标准库
- 行为-钩子-插件
- AOP-面向切面
- RBAC和Auth类的本质
- 安装iThink
- 环境要求
- 代码下载与环境配置
- 执行安装
- 体验测试模块
- apache配置
- nginx配置
- 系统架构详解
- 目录详解
- 执行流程图
- 数据字典
- RBAC 权限管理架构
- 系统分层详解
- 控制器层(controller)
- 逻辑层(logic)
- 视图层(view)
- 模型层(model)
- 服务层(service)
- 应用包架构详解
- 目录结构
- 开发规范
- 数据库规范
- 编码规范
- 功能设计原则与规范
- 后台功能详解
- 基础功能
- RBAC + Auth 权限机制
- 应用化功能机制
- 代码生成器(重要)
- 应用骨架代码生成
- 数据表 CURD 代码生成
- 页面构造器(重要)
- 通用元素构造器
- 表格元素构造器
- 搜索表单元素构造器
- 表单元素构造
- 闭包事物构造器
- 应用的开发
- 函数参考