最近在看设计模式之美这本书,通过前几章的内容学习,使得自己重新回顾了一遍java的编程思想,感觉收益匪浅,之前一直说java是面向对象编程,到底什么是面向对象,自己之前确实有过这样的想法,没想到在这本书中,作者完美的回答了我埋藏心底的疑惑,一系列的知识我觉得自己还是很想结合现在的工作经验进行一个总结,接下来就按照自己的思路(面向对象-面向过程-函数式编程-DDD建模)进行一个输出。
先来聊聊面向对象吧,因为这个是我们认识时间最长的。最大的特点就是以类和对象作为组织代码的单元以及它的四大特性
。
抽象是一种只关注功能而不关注实现的设计思路
继承最大的作用就是代码复用,后续会说明“组合大于继承”的思想
多态是指,在代码运行过程中,可以使用子类替换父类,并调用子类的方法。
这个要说的其实就是我们日常开发的思路
当我们拿到一个需求的时候,我们就会分析这个需求是要完成什么功能,中间的涉及流程以及模块都有哪些,但是你在做分析的时候,是否带着面向对象的思想去分析,或者说现在比较流行的领域思想,还是说就是无脑的直接这一块那一块的去串流程,这个是需要回过头思考的,分析之后,输出流程图,就该进行设计了。
面向需求分析的产出是详细的需求描述,面向对象设计的产出就是类。我们需要将需求描述转化为具体的类的设计。
实际工作中,前两步是比较花时间的,到编程这一步相对来说其实就比较简单了,因为基本上已经思路明确了,不过我们也是一边写,一边重构,大部分不会完全按照我们前期设计的文档,当然也不会差异的太离谱。
流程化的编程风格
比如,有一个需求,统计cpu资源利用率的情况,数据由服务A提供,如果面向过程编码,主要就是散步:
在一个方法里边搞定。也算是功能完成,虽然面向对象也是这三步,但是面向对象的基本特性,对于面向过程编程来说,却没有使用,如果后续该需求需求扩展,换了一个数据来源,对于代码的改动量是否会很大等因素,都需要进行评估了。
编程语言越高级,离机器越远,离人类越近,也就越智能
。因为面向过程的编码风格符合人的流程化思维方式,比如先干什么,再干什么;而面向对象编码风格刚相反,它是一种自底而上
的思考方式,这样的思考方式适合复杂的应用系统。
主要的特点就是函数式编程的思想,它认为:程序可以用一系列的函数或表达式的组合来表示
,是声明式编程思想的具体实践,关注的是自己需要什么
。
简单来说就是,函数内部涉及的变量都是局部变量,不像面向对象编程,共享类成员变量,面向过程编程,共享全局变量。函数的执行结果只与入参有关,与其他任何外部变量都没有关系。同样的入参,执行多少次,得到的结果都是一样的。
有状态函数
int b;
int add(int a){
return a+b;
}
无状态函数
int add(int a,int b){
return a+b;
}
函数式编程中,几乎所有传递的对象哦度不会被轻易的修改,比如下边代码
List<Integer> list = Arrays.asList(1,2,3);
list.stream().map(x->x+1).forEach(System.out::print);//加1修改
System.out.println(JSON.toJSONString(list));
输出结果
234
[1,2,3]
list并没有被修改
正是因为对象处于不变的状态,因此函数式编程更加易于并行。甚至不用担心线程安全问题。我们之所以担心线程安全问题,一个重要的原因就是当多线程对同一对象进行写操作时候,容易将这个对象写‘坏’。但是由于对象是不变的,因此在多线程环境下也就没有必要进行任何同步操作。这样不仅有利于并行化,同时,在并行化之后,由于没有锁机制,性能也会更好。
看这篇文章:函数式编程总结和应用
面向对象编程的编程单元是类和对象,面向过程编程的单元是函数,函数式编程的单元是无状态函数。
面向对象编程侧重代码模块的设计,如类的设计。面向过程编程和函数式编程侧重具体的实现,如函数的编写。
“贫血模型”将数据和操作分离,是典型的面相向过程编码风格。重Service类,轻BO类
“充血模型”将数据和业务逻辑封装在同一个类中。符合封装特性,属于典型的面向对象的编码风格。重Domain类,轻Service类