-->

后端面试38讲_18_16_设计模式基础不会灵活应用设计模式你就没有掌握面向对象编程

你好,我是李智慧。

我在面试的时候呢,喜欢问一个问题,你比较熟悉哪些设计模式?得到的回答很多时候是单例和工厂。

老实说这个回答不能够让人满意。

因为在我看来啊,单利和工厂虽然是两种经典的设计模式,但是这些创建类的设计模式并不能够代表设计模式的精髓。

设计模式的精髓在于对多肽的灵活应用,而多肽这是面向对象编程的本质所在。

我在面试的时候,有的时候也会问什么是对象,得到的回答。

各种各样对象是数据与方法的组合,对象是领域的抽象,一切都是对象对象的特性,是分装、继承、多态,这是一个比较开放的问题。

可以说这些回答都是对的,都描述了对象的某个方面。

那么面向对象的本质是什么呢?面向对象编程和面向过程编程的核心区别是什么呢?我们常说面向对象编程的主要特性是分装、继承、多态。

那么这三个特性是否是面向对象编程区别于其他编程技术的关键呢?我们先看一下分装面向对象的编程语言呢都提供了类的定义。

通过类我们可以将类的成员变量和成员方法分装起来,还可以通过访问控制符private protected public控制成员变量和成员方法的可见性。

面向对象设计最基本的设计力度呢是类类。

通过分装数据和方法构成一个相对独立的实体类之间,通过访问控制的约束互相调用,这样就完成了面向对象的编程。

但是呢分装并不是面向对象编程独有的面向过程的编程语言,比如c语言也可以实现分装特性。

在头文件点h里定义方法,而在实现文件点c文件里,能义具体的结构体和方法实现,从而是依赖头文件的外部程序,能够只访问头文件里定义过的方法,这样就实现了变量和函数的分装以及访问权限的控制。

继承似乎是面向对象编程语言才有的特性。

事实上,c语言也可以实现继承。

如果a结构体包含b结构体的定义,那么就可以理解成a继承的b定义。

在b结构上的方法呢,就可以直接执行a结构体的数据,作为一种编程技巧。

这种通过定义结构体,从而实现基层特性的方法,在面向对象编程出现以前就已经被开发者使用了。

我们再来看看多态,因为有指向函数的指针多态,事实上在c语言中也可以实现。

但是,使用指向函数的指针实现多态是非常危险的,因为这种多态没有语法和编译方面的约束,只能靠程序员之间的约定,一旦出现bug调试非常痛苦。

因此,在面向过程语言的开发中,这种多态并不能够频繁使用,而在面向对象的编程语言中,多态变得非常简单。

子类实现负类或者接口的抽象方法、程序,使用抽象负类或者接口编程,用行器注入不同的子类程序,就表现出了不同的形态,视为多态。

这样做最大的好处就是软件编程是可以实现无关性。

最后,针对接口和抽象类,编程不需要关心,具体实现是什么。

你应该还记得我在第四篇中讲到的案例。

对于一个从输入设备拷贝字符到输出设备备程序,最后具体体设备实现和拷贝程序序偶合在一起的。

那么当我们想要增加任何输入设备或者输出设备的时候,就必须要修改程序的代码。

最这个拷贝程序将会变得越来越复杂,难于使用和维护。

而通过使用接口,我们定义了reader和write两个接口,分别描述输入设备和输出设备拷贝程序。

只需要针对这两个接口编程,而无需关心具体设备是什么程序可以保持稳定,并且易于复用。

具体设备呢在程序中心期创建,然后传给拷贝程序传输成具体设备就在什么具体设备上操作拷贝逻辑。

具体设备可以像插件一样灵活插拔,使程序呈现多态的特性。

多态还颠覆了程序模块之间的依赖关系。

在习惯的编程思维中,如果a模块调用b模块,那么a模块必须依赖b模块。

也就是说a模块中的代码必须import或者using b模块的代码。

但是呢通过使用多态的特性,我们可以将这个依赖关系倒置。

也就是说,a模块调用b模块,a模块却可以不依赖b模块,反而是b模块依赖a模块。

A就是我在第十二篇中提到的依赖倒置原则,准确的说b模块也没有依赖a模块,而是依赖a模块定义的抽象接口。

A模块针对抽象接口编程,调用抽象接口。

B模块实现抽象接口。

在程序运行期将b模块注入a模块,就使得a模块调用b模块却没有依赖b模块。

多肽常常使面向对象编程表现出神奇的特性,而多肽正是面向对象编程的本质所在,正是多肽使得面向对象编程和以往的编程方式有了巨大的不同。

但是呢就算知道了面向对象编程的多态特性,也很难用好多态的特性,开发出强大的面向对象程序。

那么,到底该如何利用好多态特性呢?人们通过不断的编程实践,总结了一系列的设计原则和设计模式。

我们前几篇文章都是在讨论设计原则、开闭原则,软件的类模块应该是对修改关闭的。

而对扩展式开放的通俗的说,就是不修改代码,就实现需求的变更依赖倒置原则。

高层模块不应该依赖低层模块,低层模块也不应该依赖高层模块,他们都应该依赖抽象。

而这个抽象是高层定义的,逻辑上呢属于高层理,是替换原则。

所有能够使用负类的地方应该都可以使用它的子类替换。

但是要注意的是,能不能替换是要看应用场景的。

所以呢在设计继承的时候,就要考虑用心器的场景,而不是仅仅考虑负类和子类的静态关系。

单一职责原则。

一个类,因为只有一个引起它变化的原因,在实践中就是类文件尽量不要太大,最好不要超过一屏接口隔离原则,不要强迫调用者依赖他们不需要的方法。

方法主要是通过对接口的多重继承一个类,实现多个接口、不同接口服务,不同的调用者,不同调用者看到不同的方法,这些设计原则大部分都是和多态有关的。

不过,这些设计原则更多时候是具有指导性编程的时候,还需要依类更具体的编程设计方法。

这些方法就是设计模式,所谓模式是可重复的解决方案。

人们在编程实践中发现,有些问题是重复出现的,虽然场景各不相同,但是问题的本质是一样的,而解决这些问题的方法也是一个重复使用的。

怎么把这些可以重复使用的编程方法称为设计模式,设计模式的精髓呢?就是对多态的灵活应用。

我们以装饰模式为例,看一下如何灵活应用多态特性。

我们先定义一个接口,anything包含一个EXE方法,然后多个类实现这个接口。

装饰模式最大的特点是通过类的构造函数传入一个同类对象,也就是每个类实现的接口和构造函数传入的对象是同一个接口。

我们创建了三个类,你在文稿中可以看到这三个类的详细信息设计。

这几个类的时候呢,它们之间没有任何耦合。

但是在创建对象的时候,我们通过构造函数的不同次序,可以使这几个类互相调用,从而呈现出不同的装饰结果。

多肽的迷人之处就在于你单独看类的代码的时候,这些代码似乎平平无奇,但是一旦运行起来,就会表现出纷繁复杂的特性,所以多态有时候也会带来一些代码阅读方面的困扰,让面向对象编程的新手望而却步,这也正是设计模式的作用。

有时候你仅仅通过类的名字,比如approve debt,就能够知道设计者在使用什么模式,从而更快的理解编码。

其果你只是使用面向对象编程语言进行编程,其实并不能说明你就掌掌握。

面面对对象,编程只灵灵活,应设设计模式程序序,现出多态的特性,进而使程序健壮、灵活、清晰、易于维护和复用,这才真正掌握了面向对象编程。

所以下次再有面试官让你聊聊设计模式,也许你可以这样回答。

除了单例和工厂,我更喜欢适配奇和观察者,还有组合模式,在处理塑形结构的时候也非常有用。

通佩奇和观察者模式。

我在前面已经讲到了,设计模式是一个非常注重实践的编程技能。

通过学习设计模妙,我们可以体会到面向对象编程的种种精妙,真正掌握设计模式,需要在实践中不断的使用它,让自己的程序更加的健壮、灵活、清晰,易于复用和扩展。

这个时候面试聊设计模式更好的回答是我在工作中比较喜欢用模板模式和策略模式。

上个项目中,为了解决不同用户使用不同推荐算法的问题,我巴拉巴拉巴拉。

事实上,设计模式不仅仅包括设计模式这本书里提到的二十三种设计模式,只要是可复用用于解决某个问题场景的设计方案,都可以被称为设计模式。

关于设计模式还有一句很著名的话,精通设计模式就是忘了设计模式,这有点像张无忌学太极。

如果真正对设计模式融会贯通,你的程序中无处不是设计模式。

也许你在三五行代码中就用了两三个设计模式,你自己就是设计模式的大师,你甚至还可以创建一些自己的设计模式。

这个时候再去面试的时候,面试官也不会再问你什么设计模式的问题了。

如果问了,那么你说什么都是对的。

我在第二篇文章和本篇中都提到了可以使用组合模式便利术。

那么如何使用组合模式便利术呢?欢迎你在评论区写下你的思考,也欢迎把这篇文章分享给你的朋友,或者同事一起交流一下。