设计模式(一)

2019-09-29  本文已影响0人  guggle

    最近在学习设计模式,想和大家分享下学习心得,因为个人理解能力有限,如果理解上有偏差或者错误,希望大家能指正~

一、设计模式是什么?

     设计模式是我们在做代码设计时,可以套用的公式。一般特指1995年在由四位大佬写的《设计模式:可复用面向对象软件的基础》一书中提出的23中设计模式。

    1.代码设计?

        软件开发周期,一般是由 需求分析→ 代码设计 → 编码 → 测试,前期做的活越多越细,后期编码花的时间越少,出问题的概率越低。代码设计通俗点来说,就是想清楚代码要怎么写,想清楚之后,在编码环节就不会走冤枉路。

        大多数人学编程的历程,应该都是从C → C++ → java,OC等其他语言,实际上也是从POP(Procedure-Oriented Programming,面向过程编程) → OOP(Object-Oriented Programming,面向对象编程) → IOP(Interface-Oriented Programming,面向接口编程)

        面向过程:只要分析出处理事务的步骤,得到123步,就可以采用入口函数调用多个子函数,子函数再调用子函数的方法就行。强调的是函数。

         面向对象:先抽象成类,后对类进行封装继承多态,最后调用类的方法实现功能。强调的是类。

         面向接口:面向对象的一种,因为java,OC不支持多继承,父类只有一个,我们只能通过实现接口的方法实现多继承。

        ps:为什么很多语言会采用单继承的设计?因为多继承的话,类A可以有test方法,类B也可以有test方法,但是当一个类C继承于类A和类B时,问题就出来,类C的test方法是类A的test方法还是类B的test方法?这么弄很容易出问题,所以大多数的编程语言都采用单继承的设计。毕竟人只能有一个亲爹啊~

         以菜刀切菜切成丝这个为例,从面向过程的角度看,代码设计就需要确定操作流程,此事就三步:

         1.准备菜刀

          2.准备菜

          3.切成丝

          如果现在改成水果刀切西瓜切成块,整个步骤就变成另外的三步,如果两个事要合并在一起处理,就需要在整个操作步骤中加入是水果刀切西瓜还是菜刀切菜的判断。如若采用面向对象的方法来处理这个事,代码设计就需要确定对象和操作流程:

         1.抽象出刀这个类,成员方法是切的方法,子类是菜刀,切法是切丝,后续可以新增子类水果刀,切法是切块

         2.抽象出食物这个类,有个子类是菜,后续可以新增子类西瓜

         3.整个操作步骤,new一个刀类(准备刀),new一个食物类(准备食物),调用一个刀类的切的方法(参数为食物类)

         如果采用面向过程的写法,只要我切的对象变了,切的方法变了,我都需要在原有代码中修改,想想都头疼。只要新增一个需求,就要修改之前的代码,怎么确保代码在修改过程中不会出问题呢?测试工作怎么办?是不是在测试新需求的同时也要测试之前的老功能?如果采用面向对象的编程思路看的话,整体就简单很多了,因为步骤是固定,但是对象和方法我们只要新增就行,只要步骤不变,我们就不会修改到之前的需求。

         面向过程,能有一套共通的处理方法吗?答案显然是否定的,因为面向过程中的每一步都牵涉到具体的东西,导致就算相同的步骤操作在面向过程的代码处理过程中,其实是不一样的,也就没有共通的处理方法。所以我们说的设计模式是针对于面向对象编程过程中,可以采用的公式来处理某一类的问题。

二、设计模式有什么用?

        设计模式让我们在面向对象编程时,针对具体的问题,使用我们掌握的设计模式针对具体问题抽象,选择最符合当前需求的方案,做到高内聚,低耦合,使整个项目易复用,易扩展及易维护。

三、设计模式的基本原则

         开闭原则:说的是软件开发过程中有的接口、模块、功能能对外暴露,有的则不对外暴露。这是一个抽象的概念,之后很多的原则中都包含了开闭原则的思想。举例:一个person类,有name和age属性,name可以提供set和get方法,age只提供get方法,毕竟名字别人可以给你取,但是年龄,别人不能说你多少岁,你就是多少岁。开闭原则强调在接口设计时注意权限的事。

        单一职责原则:简单的说,一个函数一个功能,一个类对应一类的属性和接口,做到专人专事。举例:以加减乘除为例,不能定义一个函数做四种运算,而应采用四个函数,分别做加、减、乘、除四种运算。以学生,家长类为例,比如学生定义了获取考试成绩的方法,现在老师也要参加教师考试,不能为了省事,去定义一个叫某某老师的学生,调用获取考试成绩的方法。

        里氏替换原则:不要强行继承,从类的属性上看,不属于同一类的,就需要新增父类,或者修改原有父类。举例:有个person类,person类里有两个子类,古代智人类和现代人类,有步行的方法接口,现在新出来一中人,鸟人,他不是走的,是用飞的,要处理这个问题,根据里式替换原则,要不然吧父类的步行方法抽象为出行方法,要不然新增一个鸟类的父类,里面有飞行的方法,鸟人是鸟类的子类。

         依赖倒置原则:所有父类都应该是抽象类,而不是某个具体类,子类暴露给外部的接口方法也尽可能是抽象方法。

         接口隔离原则:接口隔离=单一职责+开闭,说的是一个接口负责某一类的事,暴露给外部是需要用的,不需要用到的则不对外暴露。

        迪米特法则:两个模块间如果不是紧密相关就需要引入第三者,我们在开闭原则中举的例子,外部无需和person类的name、age属性直接关联,所以应该引入第三者(get和set方法)。我们在APP开发中经常需要引入第三方网络框架,而APP代码和第三方网络框架并不是紧密相关,所以需要引入第三者,即我们APP自己的网络层,在我们的网络层代码中引用第三方网络框架的代码,这样的话,第三方框架代码改了,我们无需在所有具体业务代码中修改网络调用,只要修改APP网络层的代码即可。

        合成复用原则:少用继承,多用接口。举例:大部分子类需要新增某个方法,但是少部分子类没有这个方法,如果使用的是继承复用的方法,则父类需新增一个方法,所有子类都有了这个方法,这样在少部分类中就不符合里式替换原则,也容易导致问题,如果使用合成复用的方法,大部分类都去实现某个接口,这样才能符合里式替换原则,也符合我们的真实需求。

四、分类

        设计模式根据模式是用来完成什么工作来划分,可分为创建型模式、结构型模式和行为型模式3 种。

        创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。包含单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。

        结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,包含代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。

        行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。包含模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。

上一篇下一篇

猜你喜欢

热点阅读