设计一个官方网站推广广告,百度推广免费送网站,青岛网站建设全包,装修平台网站深入了解设计模式和设计原则 一、认识设计模式1.1、设计模式是什么#xff1f;1.2、设计模式是怎么来的#xff1f;1.3、设计模式解决了什么问题#xff1f; 二、设计模式的基础2.1、面向对象思想2.2、设计原则 三、如何学习设计模式3.1、明确目的3.2、学习步骤 总结 一、认… 深入了解设计模式和设计原则 一、认识设计模式1.1、设计模式是什么1.2、设计模式是怎么来的1.3、设计模式解决了什么问题 二、设计模式的基础2.1、面向对象思想2.2、设计原则 三、如何学习设计模式3.1、明确目的3.2、学习步骤 总结 一、认识设计模式
设计模式总共有23种首先呢我们来对设计模式有一个大致的了解带着这几个问题来思考一下
设计模式是什么设计模式是怎么来的设计模式解决了什么问题好怎么学习设计模式或者说设计模式的基础是什么如何学习设计模式
1.1、设计模式是什么
那什么是设计模式呢看设计模式的定义设计模式是指在软件开发中经过验证的用于解决在特定环境下重复出现的特定问题的解决方案。
从这个定义可以看出设计模式有很多的限定词比如“特定”、“重复特定”等。那说明什么问题呢说明设计模式在使用的时候它有很多的局限性。所以学习设计模式一定要切入它的一个本质也就是它解决一个什么问题然后再去使用它。当我们不清楚这个设计模式解决什么问题的时候不要轻易的去使用设计模式所以设计模式是适用的好。
设计模式的定义换一句都能够听懂的话就是设计模式是解决软件开发过程中一些问题的固定套路解决问题的固定套路。因此不要过度的去封装或者去使用设计模式除非我们已经确定了这个设计模式就是明确了我们的这个具体需求的变化方向而且这个变化方向的这个点呢经常的出现反复的出现那么我们才会去使用设计模式就是要使用恰当。还有一个就是设计模式类似于一个哲学或者说类似武侠小说里的一个武功秘籍一定要具备一定的工程代码量的才能够精通。但是学习设计模式还是有必要的我们要提前知道设计模式。
1.2、设计模式是怎么来的
设计模式是通过慢慢迭代出来的即它是通过满足我们设计原则之后慢慢迭代出来的。在这里提到两个重要的关键字
第一个关键字是设计原则。学习设计模式的时候首先要掌握设计原则。第二个关键字是迭代。因为重复出现所以慢慢迭代出一些固定的解决固定问题的套路。
1.3、设计模式解决了什么问题
使用设计模式有一个非常重要的前提条件就是具体的需求要既有稳定点又有变化点。只有在这种场景下既有稳定点又有变化点的这种场景下才可以使用设计模式这个前提必须要理解好。
稳定点可以理解为就是不会变的东西。变化点就是经常需要进行变化的因为具体的一个软件产品在开发当中它是长期在运行的长期需要维护进行开发的它可能是未来产生的也有可能是现在产生的设计模式就是去应对这些变化而产生的。
先想象一下两个极端。如果全是稳定点也就是软件代码呢它没有什么变化这种场景下是没有必要使用设计模式的。另外一种极端呢就是全是变化的一直都是发生改变的而且改变是没有固定的方向它也没有必要使用设计模式。这种极端通常在游戏开放中比较常见游戏开发当中呢通常用脚本语言去解决这种全是变化点的问题因为不需要重新编译、不需要重新启动脚本可以在上面写很多的复杂的功能只要重新热更新一下就行了游戏 的逻辑、还有数据就重新加载到运行的服务器当中了。
好了那么设计模式具体解决问题的场景是什么呢就是希望修改少量的代码就可以适应需求的变化。使用设计模式的时候都是希望修改少量的代码就可以适应需求的变化如果不满足设计原则可能总是需要进行重构推倒重来即代码写完了以后要推倒重来重新写好这个是不符合软件开发的一个需求的软件开发希望每次是在原来的基础上修改少量的代码就可以应对未来需求的变化设计模式就是解决这一类问题的。
举一个例子一间整洁的房间这个房间里有一个好动的猫怎么保证房间的整洁呢这个和使用设计模式要解决问题的时候的场景是一模一样的整洁的房间代表着一个稳定的点我们希望这个房间一直是整洁的。那么好动的猫是一个变化点如果这个猫到处在房间走动的话那么就会让我们整洁的房间变得不整洁现在软件开发所要解决个问题就是怎么保证房间的整洁怎么去解决这个问题呢把这个猫关在一个笼子里这样一来猫它会在有限范围内进行活动了整洁的房间也可以保证了。整洁的房间是我们的目标好动的猫是时时刻刻都可能发生改变的一些需求使用设计模式让这一个变化点在有限范围内变化。
二、设计模式的基础
设计模式跟语言也是相关的都是利用语言的特性去实现设计模式。对于C而言设计模式的基础有哪些呢第一个需要有一个面向对象的思想第二个基础是设计原则。
2.1、面向对象思想
面对对象的三个特征
封装。封装的目的是为了隐藏实现细节实现模块化写代码的时候模块化他们互相之间不干扰不影响隐藏实现细节好实现模块化。继承。C的继承跟其他语言还不太一样其他语言支持单继承只有C支持多继承。C可以继承多个接口或者是多个类。继承主要的目的是希望无需修改原有类的基础上通过继承来实现对功能的扩展。多态。这个是设计模式最重要的一个特性很多的设计模式都需要依赖多态的实现。C的多态有两种第一个是静态的多态还有一种是动态的多态。 静态的多态要是指函数的重载就是同一个函数名通过参数的不同来可以同时表现出不同的特形态。动态的多态是指继承的过程当中虚函数重写。很多的设计模式主要都需要依赖这一个特性。
类模型
上图描述的是一个多态行为classBase 是一个基类基类当中有两个方法func1和func2都是声明为虚函数还有一个class Subject类继承于这个Base类也有两个方法func2和func3需要注意func2在基类当中已经存在了func3它是一个独有方法有它的一些相对应的其他属性从它的具体的内存布局来看在Base类当中有虚函数就会生成虚函数表指针。
虚函数表指针在编译期就自动生成了当定义函数中有一个virtual这样的关键字那么编译器自然而然就会为它去生成一个虚函数表。因此在编译的时候就会把这个虚函数表的地址赋给相对应的对象就是每一个Base类的对象都会有一个虚函数表指针。那么虚函数表它是一个什么东西呢虚函数表就是一个一维数组这个一维数组当中都记录了这些虚函数的地址通过偏移就可以调到相对应的方法。
对于Base类而言有func1和func2子类class Subject同样也会有因为有virtual关键字并且基类也有virtual关键字所以编译器会为类生成一个虚函数表。当构造这个类的时候同时会把这个虚函数表的指针赋给相对应的对象并且会在这个类的最前面的位置也就是子类也会有一个虚函数表指针这个虚函数表指针它会指向一个一维数组这个一维数组会记入了相对应的函数地址如果没有去重写基类的方法的话比如class Subject类没有重写Base类的func1那么父类和子类的func1是相同的因为没有重写。当出现重写时比如class Subject类重写了Base类的func2会发生一个替换会替换为子类自己的子类自己的函数就会放在虚函数表的最后比如这里的func3是子类独有的就会放在第三个位置。
怎么来体现多态的行为呢这样
Base *obj new Subject();需要注意如果子类只是普通的继承也就是Subject就是普通的继承Base没有这种虚函数重写的话它会实现一个早绑定就是会把这个Subject这个类型转换为Base类型)如果没有这种虚函数不写那么这条语句它是属于早绑定。如果是虚函数重写了会为它生成这种虚函数表指针上面的语句它就属于晚绑定实际指向的是Subject的对象这是语言的一种机制。晚绑定的这个obj指向的是Subject的对象早绑定的话这个obj是指向的Base的对象。
晚绑定中调这个func2实际调用的是Subject对象的func2因为去找的这个虚函数表指针然后找到这个虚函数表找到了相对应的方法根据这个偏移就找到了它。这个就是晚绑定的一个原理大量的设计模式都是需要依赖这个动态晚绑定的特性。
类的关系
2.2、设计原则
前面说了设计模式怎么现在又出来了一个设计原则呢设计原则是设计模式还没有产生之前它已经出来了设计原则是我们以往一些程序在开发的过程当中总结了一些开发的原则这些原则都是针对着封装继承多态接下来跟大家介绍一下常见的九个设计原则有哪些。在项目当中要知道一块代码它到底符合什么样的设计原则。
1依赖倒置。
高层模块不应该依赖低层模块两者都应该依赖抽象抽象不应该依赖具体实现具体实现应该依赖于抽象。
用一句话来进行总结就是实现要依赖接口接口也可以把它转换成一个抽象。也就是说具体实现的代码需要去依赖这一个抽象具体去使用的这一个接口的用户也需要依赖这一个抽象。这个接口就是通常比较核心的程序员他会抽象很多很多的接口一些普通的码农就去把这些接口去实现它就行了。那么对于用户而言拿着这个接口去实现功能的时候它也是要依赖这个抽象。也就是说我们主要解决依赖导致主要解决了一个实现与我们客户使用的一个解耦中间用一个抽象层用接口来抽象这一段行为。
这里的定义就是设计模式的作者总结出来的比较抽象但是如果有一定的代码量肯定一下子能看明白。没有一定代码量的人呢这里把它抽象并举了个例子高层跟底层。
以自动驾驶为例子。自动驾驶系统公司是高层汽车生产厂商为低层它们不应该互相依赖一方变动另一方也会跟着变动而应该抽象一个自动驾驶行业标准高层和低层都依赖它这样以来就解耦了两方的变动自动驾驶系统、汽车生产厂商都是具体实现它们应该都依赖自动驾驶行业标准抽象。 通俗点说 这里举了个自动驾驶的这样一个例子有很多的车企现在自动驾驶的技术人工智能这种技术越来越成熟当大家想要去争抢这一块领域都想在自己的车上面去实现这种自动驾驶的系统。假设有一个自动驾驶系统这样的一个公司又有很多的厂商厂商跟这些自动驾驶的公司进行约定要实现相对应的跟厂商汽车相关的这些自动驾驶的系统最笨的办法就是这个自动驾驶系统根据每一个公司都去开发相对应的自动驾驶系统。
那么真正的在市场能够运行下来的一种方式是首先会有一个自动驾驶的标准接下来这些车企可以把它想象成我们的底层实现都需要依赖这一个标准也就是我们具体的一个接口就相当于一个用户要调这个接口去实现上层的一些逻辑自动驾驶也按照这个标准去实现它的这个自动驾。
总结起来依赖倒置就是说上次高层模块不应该依能依赖低层模块。换一句大家都能听懂的话就是接口的使用者不要依赖具体的实现而应该要依赖具体的接口具体的底层的实现不要依赖用户的使用方式或者是使用习惯也要依赖这个具体的接口这样子上面的变化跟下面的变化就解偶了。
2开闭原则。一个类应该对扩展组合和继承开放对修改关闭。开辟原则主要针对的是封装和多态。对扩展开放开放什么东西呢主要是指变化点对要抽象出的东西要具体的去扩展它对变化点的修改要关闭它。在这里会列一些设计原则先快速的了解要掌握则需要通过具体代码来理解设计原则这样在具体写代码的时候知道代表着一个什么含义会比较的清晰这个概念。
3面向接口。
不将变量类型声明为某个特定的具体类而是声明为某个接口客户程序无需获知对象的具体类型只需要知道对象所具有的接口减少系统中各部分的依赖关系从而实现 “高内聚、松耦合” 的类型设计方案。
设计模式主要是面向接口编程具体的实现要依赖接口具体使用接口也不要依赖具体的实现。需要注意设计原则不是一个人总结的设计原则是有很多人很多人去总结的所以肯定有重复的、有重叠的部分但是他们要有自己的侧重点自己特别强调的一部分。
4封装变化点。将稳定点和变化点分离扩展修改变化点让稳定点和变化点的实现层次分离。通常是指两个类的依赖越少越好把这些变化点尽量的不要去修改。跟开辟原则也有一点类似。看具体代码的时候就知道他们分别指向什么以及是一个什么场景。
5单一职责原则。一个类应该仅有一个引起它变化的原因。职责是一个抽象的概念是一种变化方向就是说一个封装的类它的职责不要太多了如果类的职责太多它的变化点就很多。这个和封装变化点有点像有很多重叠的部分主要关注它主要针对的是什么就行了。单一职责原则主要是针对封装和多态。
6里氏替换。子类型必须能够替换掉它的父类型主要出现在子类覆盖父类实现原来使用父类型的程序可能出现错误覆盖了父类方法却没有实现父类方法的职责。主要是说的多态就是类的虚函数重写如下图片中显示的有具体的重写代码func2函数子类的这个接口要实现他的职责。 7接口隔离。
不应该强迫客户依赖于它们不用的方法一般用于处理一个类拥有比较多的接口而这些接口涉及到很多职责客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。
8组合优于继承。继承耦合度高组合耦合度低。尽量的使用组合的方式不要使用继承的方式它主要是指封装和动态。
9最小知道原则。主要是针对封装让用户不要去选择他不需要的接口保证最小知道原则就是对类的了解越少越好只要知道几个简单的接口就行了这就是封装巧妙的地方了。
三、如何学习设计模式
接下来探讨一下如何来学习设计模式。
3.1、明确目的
什么是明确目的呢看这篇文章的朋友分为两类第一类是刚刚才开始的新手可能没有接触过具体的工程代码的书写第二类是已经在公司当中开发多年了。那么就需要明确一个学习设计模式的一个目的。
第一个目是对于基础者的也就是刚刚参与开发的朋友要知道在现有的一个公司他已经有设计模式了在使用的具体代码的基础上扩展代码。就是现在在公司里去开发那么公司的项目已经非常成熟了很多的逻辑都已经用设计原则设计模式已经封装好了此时需要解决的问题是知道这个设计模式怎么在它的上面扩展代码。第二个就是做功能抽象这是开发多年的人群了现在要做功能抽象那么如何选择设计模式。
3.2、学习步骤
探讨学习的步骤也是了解设计模式的一个步骤。
1设计模式解决了什么问题。注意跟前面说的设计模式解决了什么问题是不一样的这里讲的设计模式是具体的某一个设计模式。写一个设计模式该设计模式解决了什么问题。那么解决什么问题呢一定要知道它的稳定点是什么选择这个设计模式来解决问题的稳定点是什么以及它的变化点是什么要分析出来这个是第一步。
2该设计模式的代码结构是什么样子也就是说未来在开发的过程当中看到一段代码通过观察这个代码结构快速的能够判定他是什么设计模式。这也是学习的一个目的一定要非常非常清楚。学到的某一个设计模式它的代码结构是什么好这个代码结构包括C、C语言它来实现这个设计模式通常采用什么样的一个结构来实现好它的代码结构是什么一定要清楚。
3符合哪些设计原则。这个一定要清楚因为在平常开发的过程当中一开始的时候根本不知道这个业务未来是怎么变化那怎么办呢首先要先写符合设计原则的代码当写代码符合设计原则的时候未来想要把这个代码修改成为某一个设计模式只需要改少量就可以把设符合设计原则的代码把它转化成设计模式。符合哪些设计原则这个就是为什么要学习符合哪些设计原则。
4如何扩展代码。就是在具体现有的代码上面怎么去扩展代码。注意通常这种扩展代码都是应对的一个变化点大家注意它是一个变化点一定要把这个变化点分析出来具体设计模式它到底解决了一个什么样的变化点以及它的稳定点是什么。变化点通常是扩展的方式来进行修改只有这个样子才能够写少量改少量的代码以应对未来需求的变化这个必须要掌握好。
5该设计模式有哪些典型应用场景。学习设计模式的时候一定要知道它有哪些典型应用这个主要用来解决做知识迁移学了设计模式未来在工作当中怎么去使用它。为什么学习某一个具体知识的时候一定要把它的典型场景应用把它给整理一下呢因为自己学习的时候学的都是比较抽象的通常第一步去理解他理解只是说明你理解他了知道他的一个逻辑关系了从理解到能够自如的去使用它就是做知识迁移还有一个步骤的即需要多思考、多实践才能够来实现知识迁移多重复重复、重复、不断的去重复重复的理解。再加上去总结一些典型的应用场景就可以做知识迁移。
设计模式有哪些典型应用怎么学习呢
可以联系目前自己的工作场景然后去分析是不是适合某一个设计模式。工作场景中恰好要使用到某一个设计模式然后去总结一下场景为什么要使用这个设计模式为未来的时候做知识迁移的时候好提供帮助。或者在某一个开源框架当中去总结他使用这个设计模式解决了什么问题然后他是具体是怎么变化使用的。
总结
思维导图 设计模式是软件开发中常用的解决问题的模板它是通过对软件开发中经常遇到的问题进行总结和抽象产生的。设计模式的基础是面向对象思想和设计原则通过对这些基础知识的理解可以更好地学习和应用设计模式。为了有效地学习设计模式首先需要明确学习的目的然后按照一定的学习步骤系统学习才能够真正掌握设计模式的精髓。通过本文的介绍读者将更加深入地认识设计模式以及学习设计模式的方法。
书籍推荐
《设计模式-可复用面向对象软件的基础》《重构与模式》