泛型编程(Generic Programming)最初提出时的动机很简单直接:发明一种语言机制,能够帮助实现一个通用的标准容器库。
泛型编程要解决什么问题
- 算法的泛型
- 类型的泛型
- 数据结构的泛型
比如如果我要在一个hashtable中查找一个key,返回什么呢?
一定不是返回“索引下标”。
因为在hashtable这样的数据结构中,数据存放位置不是顺序的,而且会因为容量不够的问题,被重新hash后改变,所以返回下表是没有意义的。
对此,我们要把事情做得泛型和通用一些。
如果找到,返回找到的这个元素的一个指针 会更靠谱一点。
可以这么理解。
- 用模板技术来抽象类型,这样可以写出类型无关的数据结构。(泛型的数据容器)
- 使用一个迭代器来遍历或是操作数据结构内的元素。(泛型的数据容器的迭代期)
在弱类型语言中,以function为参传入method为某一场景提供宽泛的支持,是为泛型编程的典型例子。
编程世界中,我们需要处理好两件事情。
一、编程语言的类型问题
二、对真实世界中业务代码的抽象,重用和拼装。
类型系统定义如何将编程语言中的数值和表达式归类为许多不同的类型,以及如何操作这些类型,以及这些类型中的相互作用。
类型可以确定一个值或者一组值,具有的特定的意义和目的。
类型允许程序设计者以较高层次的方式思考,而不是烦人的低层次实现。
这就要考虑到。
- 程序语言的安全性
- 利于编译器的优化
- 代码的可读性
- 抽象化
类型带来的问题就是作用于不同类型的代码,虽然长得非常相似,但由于类型的问题需要不同版本写出不同算法,如果要做到泛型,就需要涉及比较底层的玩法。
我们需要清楚地址到,无论哪种程序语言,都避免不了一个特定的类型系统。
静态类型检查是在编译器进行语义分析时进行。
如果一个语言强制实行类型规划,称为强类型;反之,称为弱类型。
任何语言都有类型系统。
类型是对内存的一种抽象。不同类型,会有不同的内存布局和内存分配策略。
不同的类型,有不同的操作,所以,对于特定的类型,也有特定的一组操作。
要想做好泛型编程。
- 标准化类型的内存分配
- 标准化类型的操作
- 标准化数据容器的操作
- 标准化类型上特有的操作
屏蔽掉数据和操作数据的细节,让算法更为通用,让编程者更多地关注算法的结构,而不是在算法中处理不同的数据类型。
编程语言本质上帮助程序员屏蔽底层机器代码的实现,而让我们可以更为关注业务逻辑代码。
但因为,编程语言作为机器代码和业务逻辑的粘合层,是在让程序员可以控制更多底层的灵活性,还是屏蔽底层细节,让程序员可以更多地关注逻辑,这是很难两全的。
函数式编程
函数式编程是将运算过程尽量写成一系列嵌套的函数调用。
关注的是做什么,而不是怎么做,因为被称为声明式编程。
函数式编程是具备一定的代码扩展能力的。
面向对象
优点
- 能和真实的世界交相辉映,符合人的直觉
- 面向对象和数据库模型设计类型,更多关注对象间的模型设计
- 强调“名次”而非“动词”,更多关注对象和对象的接口
- 根据业务的特征形成一个个高内聚的对象
缺点
- 代码都需要附着在一个类上,从侧面上说,其鼓励了类型。
- 代码需要通过对象来达到抽象的效果,导致相当厚重的“代码粘合层”
因为太多封装以及对状态的鼓励,导致了大量不透明并在并罚下出现很多问题。
编程的意义
Program = Logic + Control + Data。
Logic部分才是真正有意义的。
Control部分只是影响Logic部分的效率。
Control是可以标准化的。
比如:遍历数据、查找数据、多线程并发、异步等,都是可以标准化的。
Control需要处理数据,所以标准化Control。
需要标准化Data Structure,我们可以用泛型编程来解决这个问题。
Control还要处理用户的业务逻辑,即Logic,所以我们可以通过标准化接口\协议来实现,就是我们的Control可以适配任何的Logic。
有效分离Logic、Control和Data是写出好程序的关键所在。
有一些策略是可以借鉴的。
状态机
- 状态定义
- 状态变迁条件
- 状态的action
DSL-Domain Specific Language
- HTML、SQL、Unix 、正则
编程范式
- 面向对象
- 委托
- 策略
- 桥接
- 修饰
- ZOC/DIP
- MVC。。。
- 函数式编程
- 修饰
- 管道
- 拼装
- 逻辑推导式编程
- Prolog