-->

左耳听风_036_35_编程范式游记6-_面向对象编程

你好,我是沈浩网名猪耳朵house.那这里呢我再提个醒,这一系列的课程中啊会出现大量的代码,你只听音频啊,很难听懂,一定要打开文稿啊,配合着音频来学习。

好了,我们这节课呢正式开始。

那前面我们谈了函数式编程,那函数式编程总结起来呢,就是把一些功能或者逻辑代码,通过函数拼装的方式来组成的玩法。

那这其中呢涉及最多的是函数啊,也就是编程中的代码逻辑。

但是呢我们知道代码中呢还是需要处理数据的那这些呢就是所谓的状态。

函数式编程呢需要我们写出无状态的代码。

但是这天下并不存在没有状态,没有数据的代码。

那如果函数式编程不处理状态,这些东西那状态会放在什么地方呢?总得需要一个地方来放这些数据吧。

那对于状态和数据的处理呢,我们有必要提一下面向对象编程这个编程范式。

我们知道面向对象的编程呢有三大特性啊,分别是封装、继承和多态。

那面向对象编程呢是一种具有对象概念的程序编程泛型。

那同时呢也是一种程序开发的抽象方针,那它可能包含数据属性、代码与方法。

那对象呢指的是类的实力,他把对象作为程序的基本单元,将程序和数据啊封装在里面,从而提高软件的可重用性、灵活性和可扩展性。

那对象里的程序呢可以访问和修改对象相关联的数据。

在面向对象编程里呢,计算机程序啊会被设计成彼此相关的对象。

那面向对象呢程序设计思想呢可以把程序啊看作包含了各种独立而又相互调用的对象。

那这个呢与传统的思想刚好相反,那传统的程序设计呢主张将程序看作一系列函数的集合,或者呢直接就是一系列对计算机下达的指令。

而面向对象程序的设计呢,它的每一个对象都应该能够接收数据处理数据啊,并将数据啊传达给其他的对象。

所以呢他们都可以被看作一个小型的机器啊,也就是对象。

那目前呢已经被证实面向对象的程序设计推广了程序的灵活性和可维护性,并且在大型项目设计中呢广为应用。

此外呢他的支持者还声称,面向对象程序设计要比以往的做法更加便于学习。

因为它能够让人们更简单的设计,并维护程序使程序啊更加便于分析设计和理解。

那现在呢几乎所有的主流语言啊都支持面向对象啊,比如common list、 python、 c加加objective c small talk,还有delphin、 java、 swift c sharp pro、 ruby,还有PHP啊等等。

那说起面向对象呢,就不得不提一本书叫做设计模式,可复用面向对象软件的基础。

那这本书呢一共收录了二十三种设计模式。

你在课后呢可以点开门店的链接啊,看一下。

那这本书的二十三个经典的设计模式呢啊基本上就是说了两个面向对象的核心理念。

那第一个呢叫做program turn interface, not an implementation.那具体含义呢有四点。

那第一点呢是使用者不需要知道数据类型结构算法的细节。

那第二点呢是不需要知道实现的细节啊,只需要知道提供的接口。

那第三点呢是要利于抽象封装、动态绑定和多态。

那最后呢是符合面向对象的特质和理念。

那第二个核心理念呢叫做favorably comversition over classing hheritanes.那它的具体含义呢同样也有四点。

那第一点呢是继承需要给子类暴露一些负类的设计和实现细节。

那第二点呢是父类实现的改变,会造成子类啊也需要改变。

那第三点呢是我们啊以为继承主要是为了代码重用,但实际上在子类中呢需要重新实现很多负类的方法。

那最后呢是继承更多的应该是为了多态。

那为了讲清楚这两个核心理念呢,我们先来看一个拼装对象的例子。

那假设呢我们有四个物体啊,分别是木头桌子、木头椅子、塑料桌子和塑料椅子。

那还有四个属性啊,分别是燃点、密度、价格和重量。

那么我们怎么用面向对象的方式来设计我们的类呢?那我们呢可以参考文中的这张类图,那图的左边呢是材质类material,那它的属性呢有燃点和密度。

那图的右边呢是家具类furniture,那它的属性呢有价格和体积,在furniture中呢耦合了material,而具体的material是would还是plastic.那这个呢在构造对象的时候啊注入到furniture里面就好了。

那这样呢在家具类中,通过材料的密度属性和家具的体积属性啊,就可以计算出重量属性了。

那这样设计的优雅显而易见,它能和现实世界啊相对应起来,而且呢材料类啊是可以重用的那这个模式呢也表现了面向对象的啊拼装数据的另一个精髓啊,就是喜欢组合,而不是继承。

那这个模式呢在设计模式里啊叫做桥接模式啊,也叫bridge模式。

那对比函数式编程来说呢,函数式啊强调动词,而面向对象呢强调名词面向对象更多的关注接口间的关系啊,通过多态来适配不同的具体实现。

那接下来呢我们再来看一个拼装功能的例子。

我们的需求呢是处理电商系统的订单。

那处理订单呢有一个关键的动作啊,就是计算订单中的价格。

那有的订单呢需要打折,有的呢不打折。

那在进行面向对象编程的时候呢啊假如我们用java语言,那我们呢就需要先写一个接口bilding strategy.那其中一个方法呢就是get act price输入一个原始的价格啊,输出一个根据相应的策略计算出来的价格。

那这个接口呢很简单啊,只是对接口的抽象与实现无关。

然后呢我们对这个接口啊进行实现。

那这里呢我实现了两个策略,一个呢是不打折的normal strategy.那一个呢是打到五折的heavy hour strategy.于是呢我们先封装了一个订单项order item.那其中呢包含了每个商品的原始价格和数量啊,还有计算价格的策略。

然后呢,在我们的订单类order中封装order item的列表啊,也就是商品列表。

并且在操作订单添加购买商品的时候呢,加入一个计算价格的building strategy.最终呢我们在pay builill函数中啊,把整个订单的价格明细和总价打印出来。

那在这个例子中呢,我们可以看到我们把定价策略和订单处理的流程分开了。

那这么做的好处呢,就是我们可以随时给不同的商品啊注入不同的价格计算策略。

那这样一来呢就有很高的灵活度了。

那剩样的事呢就交给我们的运营人员来配置不同的商品,使用什么样的价格计算策略了。

那这里呢我们需要注意在现实社会中呢,订单价格的计算会比这个事儿复杂的多。

比如有会员价,有打折卡啊,还有商品的打包价等等,而且呢还可以叠加不同的策略。

我们这里呢只是为了说明面向对象编程的范式啊,所以故意的简单化了。

那其实呢这个设计模式啊就叫做策略模式。

我认为呢这是设计模式中啊最为经典的模式了,它充分体现了面向对象编程的方式。

我们啊再来看一个例子,有关资源管理的那文章中呢有一段代码,如果你仔细看一下呢,就会发现这段代码是有问题的。

因为那个if语句在返回的时候呢,没有把锁给unlock掉。

那这样呢会导致锁没有被释放。

那如果我们要把代码写对啊,就需要在return前unlock一下。

但是呢在所有函数退出的地方都要加上unlock语句,那这样呢会让我们的代码维护起来变得很困难。

于是呢我们就可以使用面向对象呢变成模式,先设计一个代理类lock guard.那这个lock二ard呢会持有一个锁,它的构造函数里面啊会去加这个锁,在析构函数里面去解锁。

那这样呢用这个log art啊,我们就可以优雅的解决锁释放的问题了。

那这个技术呢就叫做III resource acquisition is虽源获取就是初始化。

那这个呢是inititializzc i加中一个利用用面向对对的技术,而这个设计模式呢叫做代理模式。

我们可以把一些控制资源分配和释放的逻辑啊交给这些代理类。

然后呢,我们只需要关注业务逻辑代码就可以了。

而且呢在我们的业务逻辑代码中啊,减少了这些和业务逻辑不相关的程序控制的代码。

那从刚刚的代码中呢,我们可以看到几个面向对象的事情。

那首先呢我们使用接口抽象了具体的实现类,然后呢其他类耦合的是接口,而不是实现类。

那这个呢就是多肽,它增加了程序的可扩展性,因为这就是接口编程。

所谓接口呢也就是一种协议,就像HTTP协议一样,浏览器和后端的程序呢都赖于这一种协议,而不是具体的实现。

那如果是依赖具体实现呢,那么浏览器啊就要依赖后端的编程语言或者中间件了,那这个呢就太恶心了。

所以呢浏览器和后端的程序啊就完全解除了依赖关系啊,而去依赖一个标准的协议。

那这个呢就是面向对象呢变成范式的精髓,那同样呢也是控制反转依赖倒置的本质。

那最后呢我们来讲一下LC控制反转。

那关于LC的概念啊,它提出来已经很多年了,它被用于一种面向对象的设计。

我在这里呢再简单回顾一下这个概念,我先谈技术啊再说管理。

比如呢我们有一个开关要控制一个灯的开和关这两个动作。

那最常见啊也最没有技术含量的实现呢啊就是图中这样我创建一个total switch类啊,表示开关再建一个light类啊表示灯,然后让这个total switch啊去依赖这个light.然后呢,有一天我们发现需要对灯泡扩展一下,于是呢我就把这个light做成了抽象类,让不同种类的灯泡啊,也就是bobble light和tube light去实现这个抽象类。

那但是呢又有一天我们发现这个开关啊可能还要控制别的啊,不单单是灯泡的东西。

据发现这个开关呢还是耦合的灯泡这种类别啊非常不利于扩展。

于是呢反转控制就出现,就像现实世界一样,造开关的工厂呢根本不关心要控制的东西啊是什么?它只做一个开关应该做好的事儿,那就是把电接通,把电断开。

而我们造各种各样灯泡的工厂呢,也不用关心你用什么样的开关,反正呢我只管把灯的电源接口给做出来就好了。

然后呢,开关厂和电灯厂依赖于一个标准的通电和断电的接口,那这样呢就产生了LC控制反转。

那所谓控制反转呢,意思就是开关从以前设备的专用开关转变到了控制电源的开关。

而以前的设备呢又反过来依赖开关厂声明的电源连接接口。

那只要符合开关厂定义的电源连接的接口,那这个开关呢就可以控制所有符合这个电源连接接口的设备。

也就是说呢我们从开关依赖设备这种情况变成了设备啊,反过来依赖于开关所定义的接口。

那这样的例子呢在生活中太多见了。

比如说钱呢就是一个很好的例子。

以前大家呢都是以物易物,所以呢在各种物品交易之前呢,都需要相应的交易策略。

比如说一头羊换两袋米,一袋米呢,换一斤猪后腿肉啊等等。

这种换算太复杂了,于是呢钱就发明出来了。

那所谓钱呢,其实就是一种交易协议,所有的商品呢都依赖这个协议啊,而不用再互相依赖了。

于是整个事界的运作呢就简单了很多。

那在交易的过程中呢,卖家向买家卖东西,一手交钱一手交货。

所以啊基本上来说呢,卖家和买家必须强耦合啊,也就是必须见面。

那这个时候呢,银行出来做担保,买家呢先把钱垫到银行,然后银行呢让卖家发货,然后买家验货之后呢,银行再把钱打给卖家。

那这个呢就是反转控制。

买卖双方呢把对于对方的直接依赖和控制反转到了让对方啊来依赖一个标准的交易模型的接口。

那股票交易啊也是一样的,那证交所呢就是买卖双方的标准交易模型接口。

那刚刚这个例子呢可能还不明显。

那我们再举一个例子,海尔公司呢作为一个电器制造商,需要把自己的商品啊分销到全国各地。

那但是呢发现不同的分销渠道啊有不同的玩法。

于是呢就派出了各种销售代表玩不同的玩法。

那随着渠道越来越多,发现每增加一个渠道,就要新增一批人和一个新的流程,严重耦合并依赖各渠道商的玩法。

那最后呢实在是受不了了,于是呢就制定业务标准,开发分销信息化系统。

只有符合这个标准的渠道商,才能成为海尔的分销商,让各个渠道商啊反过来依赖自己的标准反转的控制导致了依赖。

那这个思维方式啊其实还深深的影响了很多的东西啊,比如我们的系统架构,比如云计算平台中啊有很多的云产品线。

那一些底层服务的开发团队呢,只管开发底层的技术,然后呢什么也不管,就交给上层的开发人员。

那上层的开发人员呢在底层团队开发出来的产品上面啊,开发各种管理这个底层资源的东西啊,比如生产底层资源的业务,底层资源的控制台,底层资源的监控系统等等。

但是呢随着接入的资源越来越多,上层给各个云资源控制,生产开发控制台和监控的团队啊完全干不过来了。

那这个时候呢依赖道士和反转控制啊,又可以解决问题了。

为了有统一体验,各个云产品线,需要遵从一定的协议或规范来开发。

比如每个云产品团队呢都需要按照标准定义相关资源的生命周期管理,提供控制台接入整体监控系统。

通过标准的协议开发控制系统,我再举一个例子啊,就是集中式处理电子商务订单的流程。

那各个垂直业务线呢都需要通过这个平台来处理自己的交易业务。

但是呢垂直业务线上的个性化需求啊太多了。

于是呢这个技术平台开始发现,来自各个业务方的需求应接不暇,各种变态需求啊严重干扰系统,各种技术决策越来越不好做,导致需求排期排不过来。

那这个时候呢也可以使用依赖倒置和反转控制的思想来解决问题。

我可以开发一个插件模型,工作里有引擎,还有pub和sub系统。

让业务方的个性化需求啊支持以插件的方式啊插入到订单流程中。

那业务方自己的数据啊存在自己的库衷,业务逻辑呢也不要侵入系统,还可以使用工作流引擎啊,或者pub sum的协议标准,来自己定义工作流中的各个步骤。

那甚至呢还可以把工作里有引擎的各个步骤的decider交给各个业务方自行处理,让各个业务方来依赖于标准,插件和工作流接口反转控制,让他们来控制系统依赖道置,让他们来依赖标准。

那刚刚这些例子啊,我到底想说什么呢?啊,其实我想说的是,我们每天啊都在标准化和定制化中纠结,我们痛苦于哪些?应该是平台要做的,哪些呢?应该是要甩出去的那这里面呢会出现大量与业务关的软件或中间件啊,包括协议、数据接口等等。

那通过面向对象的这些方式啊,我们就可以通过抽象来解耦,或者呢通过中间件来解耦。

那这样呢可以降低软件的复杂度。

那总而言之呢,我们就是想通过一种标准来让业务更为规范。

好了,这节课到这里呢就结束了。

那最后呢我们来简单总结一下面向对象的优缺点。

那首先呢来说一下优点。

那第一呢面向对象能和真实的世界啊交相呼应,符合人的直觉。

那第二呢面向对象和数据库模型来设计类型更多的关注对象间的模型设计。

那第三呢,面向对象强调名词,而不是动词,更多的关注对象和对象间的接口。

那第四呢,根据业务的特征,形成一个个高内聚的对象,有效的分离了抽象和具体实现,增强了可重用性和可扩展性。

那第五呢,面向对象变成了拥有大量非常优秀的设计原则和设计模式。

另外呢solid啊也就是单一功能开闭原则里时替换接口隔离以及依赖反转。

那这些呢是面向对象设计中的五个基本原则,还有呢LC和DIP啊等等。

当然呢它也有一些缺点。

第一呢就是代码都需要附着在一个类上。

那从某种程度上来说呢,它鼓励了类型数量的膨胀。

那第二呢代码需要通过对象来达到抽象的效果。

那这样呢就导致了相当厚重的代码粘合层。

那第三呢,因为太多的封装啊以及对状态的鼓励,导致出现了大量的不透明,而且在病发下会出现很多的问题。

当然还是有好多人啊并不喜欢面向对象,尤其是喜欢函数式和范型的那些人啊,似乎都是非常讨厌面向对象的那通过对象来达到抽象,结果,把代码呢分散到不同的类里面。

然后呢要让他们执行起来,就需要把这些类啊粘合起来。

所以呢他另外一方面啊,鼓励相当厚重的代码粘合层。

那所谓代码粘合层呢,就是把代码粘合到这里面。

在java里面有很多的注入方式,像spring那些注入啊鼓励粘合。

所以呢就导致了大量的封装啊,完全不知道里面啊在干什么事情。

而且呢封装屏蔽了细节啊,具体发生啥事啊,你还不知道。

那这些呢都是面向游象不太好的地方。

那文末呢是编程范式游记系列文章的目录啊,方便你了解这一系列内容的全貌。