换种思路去理解设计模式(上)转自王福朋大神

2024-04-14 07:38

本文主要是介绍换种思路去理解设计模式(上)转自王福朋大神,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


最近一直在了解学习设计模式相关知识,还得先从宏观把控啊,参考链接:http://www.cnblogs.com/wangfupeng1988/p/3748514.html

1 前言

  看过许多关于设计模式的博客,也读过关于设计模式的书。几乎所有的介绍的开头,直接就引入了“设计模式”或者“某某模式”。设计模式到底是因什么而来?这是一个很重要的问题。孙悟空从石头缝里蹦出来,《西游记》还介绍了这个石头的来历呢。

  要想了解一个东西,至少有“3W”——what、why、how——是什么、为什么、怎么用。看现在大部分的文章或者书籍,重点介绍的还是“what”,这就有点类似于:为了用设计模式用设计模式。在这种思想的教导下去了解设计模式,学不会也很正常。

     另外,介绍一个东西的用处时,不要弄一些小猫小狗、肯德基、打篮球、追MM这话总例子。这就像用小学课本的儿童故事来给你讲解一个人生道理一样,你听着明白,但是真能理解吗?

 

2  概述

  记得之前看过一篇博客,具体内容现在都忘记了。记得上面有句话大体是什么说的:所谓的设计模式,我们日常工作中经常用,只是我们没有想过像GoF一样,把这些日常用到的模式总结归纳,形成结构化的理论。

  可见,设计模式不真正是GoF提出的概念,而是他们作为一个有心人,把人们日常工作中遇到的设计问题,全面的总结,才形成了之后的“23种设计模式”。

   首先,设计模式解决的肯定是系统设计问题,而且会用到面向对象来解决的。所以,本书开头先说设计原则和面向对象。面向对象基础知识,大部分人应该都了解;至于设计原则,不了解的人必须要先了解。

  其次,我们将模拟一个简单的对象声明周期过程,从对象的创建、封装、组合、执行和操作,一步一步走来,会遇到许多情况和问题。针对问题,我们将通过思考,利用面向对象和设计原则,解决这个问题。而解决这个问题的方法,便是一种设计模式。

  最后,23种设计模式不是一盘散沙,是有关系的。就是对象的生命周期一步一步的将各个设计模式串联在了一起。对象的生命周期中,会一步一步的遇到总共23种设计问题,所以才会有23种设计模式。

3  设计原则

  设计模式解决的肯定是系统设计的问题,所以首先从“设计”说起。

  设计所要解决的主要问题,是如何高效率、高质量、低风险的应对各种各类变化,例如需求变更、软件升级等。设计的方式主要是提取抽象、隔离变化,有5大设计原则——“SOLID”,具体体现了这个思路。

  • S - 单一职责原则:

  一个类只能有一个让它变化的原因。即,将不同的功能隔离开来,不要都混合到一个类中。

  • O - 开放封闭原则:

  对扩展开放,对修改封闭。即,如果遇到需求变化,要通过添加新的类来实现,而不是修改现有的代码。这一点也符合单一职责原则。

  • L - Liskov原则:

  子类可以完全覆盖父类。

  • I - 接口隔离原则:

  每个接口都实现单一的功能。添加新功能时,要增加一个新接口,而不是修改已有的接口,禁止出现“胖接口”。符合单一职责原则和开放封闭原则。

  • D – 依赖倒置原则:

  具体依赖于抽象,而非抽象依赖与具体。即,要把不同子类的相同功能抽象出来,依赖与这个抽象,而不是依赖于具体的子类。

 

  总结这些设计原则可知,设计最终关注的还是“抽象”和“隔离”。面向对象的封装、继承和多态,还有每个设计模式,分析它们都离不开这两个词。

4  面向对象基础

  继承、封装、多态

  接口、抽象类

5  一个对象的生命周期

  一个对象在系统中的生命周期可以概括为以下几点:

  • 对象创建:

  想到对象创建,最多的就是通过new一个类型来创建对象。但也会有许多特殊的情况,例如对象创建过程很复杂,如何解耦?等等。

  • 对象组合、包装:

  一个对象创建后,可能需要对其就行包装或者封装,还可能由多个对象组成一个组合结构。在这过程中,也会遇到各种问题。

  • 对象操作:

  对象创建了,也组合、包装完毕,然后就需要执行对象的各种操作,这是对象真正起作用的阶段。对象的操作情况众多,问题也很多。

  • 对象消亡:

  直到最后对象消亡,在C#中将被GC回收。

 

  以上简单介绍这个过程,其中的具体描述以及遇到的情况和问题,会在下文中详细讲解

6   创建一个对象

6.1   过程描述

一般对象的创建可以new一个类型,相信系统中绝大部分的对象创建也是这么做的。但是如果遇到以下情况,直接用new一个类型,会遇到各种各样的问题。

6.2   情况1:拷贝创建

  系统中肯定会遇到这种情况,新建对象时,要用到一个现有对象的许多属性、方法等。这时候再通过new一个新的空对象,还需要把这些属性、方法都赋值到新对象中,带来不必要的工作量。

  提出这个问题,我们会想到克隆,也可能已经在系统中用到了克隆。其实这个就是一个比较简单的设计模式——原型模式。我们把这个“克隆”动作抽象到一个接口中,需要克隆的类型,实现这个接口即可。

        

         C#已经在FCL(Framework Class Library)中定义了一个接口——IColoneable,因此不需要我们在自己定义该接口,只需要在用到的地方实现即可。IColoneable接口只定义了一个Colone方法:

        

  例如FCL中的String类,实现了IColoneable接口,并实现了接口方法Colone()。

        

 

6.3  情况2:限制单一对象

  如果一个对象定义的属性和方法,可供系统的所有模块使用,例如系统的一些配置项。此时无需再去创建多个对象。也不允许用户创建多个对象,因为一旦修改,只修改这一个对象,系统的所有模块都将生效。

  我们把这个只能实例化一次的对象叫做“单例”,这种模式叫做单例模式

  其实系统中的静态类,就是这种“单例”的设计思想。例如FCL中的Console类,它是一个静态类,它给系统提供的就是一个“单例”类。

   

  只不过Console是一个类型,而不是对象,缺点就是无法作为对象赋值和传递。如果系统中需要的“单例”就是一些功能,涉及不到对象的赋值和传递,完全可以用静态类实现,没必要非得用单例对象。

  对象的单例模式,关键在于限制类型的构造函数,不让使用者随意new一个新对象,且看代码:

  

  重点:将构造函数设置为private,只能内部调用;用一个静态字段来存储对象。

  可见,无论单例是类型还是对象,都需要通过“静态”来实现。

6.4   情况3:复杂对象

  创建一个新对象时,一般需要初始化对象的一些属性。简单的初始化可以用通过构造函数和直接赋值来完成。

  

  但是如果一个对象的属性过多,业务逻辑很复杂,就会导致复杂的创建过程。这种情况下,用构造函数是不好解决的。如果用直接赋值,就会导致大量的if…else…或者switch…case...的条件判断。这样的代码将给系统的维护和扩展带来不便,而且如果不改变设计,会随着维护和扩展,会出现更多的条件判断。随着代码量的增加,维护难度更大。如果再是多人同时维护,那就麻烦了。

  

  显然,这样的代码不是我们所期望的。设计上也不符合单一指责原则、开放封闭原则。所以,对于一个复杂对象的创建过程,我们将考虑重构。

  我们把对象创建的过程抽象出来,做成一个框架,然后派生不同的子类,来实现不同的配置。将复杂对象的构建与其表示分离,这就是建造者模式

  

  上图中,我们最终要创建的是Product类型的对象,Product是个复杂对象。如果直接new一个对象,再赋值,会导致大量条件判断。

  所以,我们将对象创建过程抽象到一个Builder抽象类中,然后用不同的子类去实现具体的对象创建。这样的设计相比之前大量的if-else-代码,优势是非常明显的,并且符合单一职责原则和开放封闭原则。应对需求变更、新功能增加、多人协同开发都是有好处的。

6.5   情况4:功能相同的对象

  最经典的就是数据操作。创建一个用于SQL server的SQLDBHelper类,又创建了一个用于Oracle的OracleDBHelper类,这两个类所实现的功能是完全一样的,都是增删改查等。如果这两个类是孤立的,那系统数据库切换时候,将导致SQLDBHelper和OracleDBHelper两个类之间的切换,而且改动工作量随着系统复杂度增加。

  

  而且如果增加一个数据库类型,也会导致系统代码的大量修改。

  

  这个问题的根本是违反了依赖倒置原则。客户端应该依赖于抽象,而不是具体实现。我们应该把数据操作的功能抽象出来,然后通过派生子类来实现具体。

  

  这样设置之后,我们创建对象的代码就会变成:

  

  面对不同的数据库,我们需要判断并创建不同的实现类。

  

  可以把这段代码封装成一个方法,这就是一个简单的“工厂”。所谓工厂,就是封装一个对象创建过程,对于一种抽象,到底由哪个具体实现,由工厂决定。

  

  这是一个简单工厂模式。另外,工厂方法模式抽象工厂模式也都是在这个基础上再去抽象、分离,而出来的。

6.6   总结

  对象创建并不是new一个类型这么简单,以上四种情况在日常开发过程中应用也都比较常见。

  上面通过对象创建过程的种种情况,随之介绍出了:原型模式、代理模式、建造者模式、工厂模式。虽然现在还不能完全了解这些模式的细节,但是至少明白了这些模式应对什么问题,有了明确的定位。而这才是最关键的,有了定位,有了高层次的理解,再看细节就变得容易多了。

 

后文继续,敬请期待!

---------------------------------------------------------------------------------------------

7. 多对象组成结构

7.1 过程描述

7.2 情况1:借用外部接口

7.3 情况2:给对象增加新功能

7.4 情况3:封装功能

7.5 情况4:递归关系的组合

7.6 情况5:分离多层继承

7.7 情况6:封装组合,供客户使用

7.8 总结

 

8. 对象行为与操作对象

…… 

这篇关于换种思路去理解设计模式(上)转自王福朋大神的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/902464

相关文章

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

如何通俗理解注意力机制?

1、注意力机制(Attention Mechanism)是机器学习和深度学习中一种模拟人类注意力的方法,用于提高模型在处理大量信息时的效率和效果。通俗地理解,它就像是在一堆信息中找到最重要的部分,把注意力集中在这些关键点上,从而更好地完成任务。以下是几个简单的比喻来帮助理解注意力机制: 2、寻找重点:想象一下,你在阅读一篇文章的时候,有些段落特别重要,你会特别注意这些段落,反复阅读,而对其他部分

深入理解数据库的 4NF:多值依赖与消除数据异常

在数据库设计中, "范式" 是一个常常被提到的重要概念。许多初学者在学习数据库设计时,经常听到第一范式(1NF)、第二范式(2NF)、第三范式(3NF)以及 BCNF(Boyce-Codd范式)。这些范式都旨在通过消除数据冗余和异常来优化数据库结构。然而,当我们谈到 4NF(第四范式)时,事情变得更加复杂。本文将带你深入了解 多值依赖 和 4NF,帮助你在数据库设计中消除更高级别的异常。 什么是

三相直流无刷电机(BLDC)控制算法实现:BLDC有感启动算法思路分析

一枚从事路径规划算法、运动控制算法、BLDC/FOC电机控制算法、工控、物联网工程师,爱吃土豆。如有需要技术交流或者需要方案帮助、需求:以下为联系方式—V 方案1:通过霍尔传感器IO中断触发换相 1.1 整体执行思路 霍尔传感器U、V、W三相通过IO+EXIT中断的方式进行霍尔传感器数据的读取。将IO口配置为上升沿+下降沿中断触发的方式。当霍尔传感器信号发生发生信号的变化就会触发中断在中断

Jenkins 插件 地址证书报错问题解决思路

问题提示摘要: SunCertPathBuilderException: unable to find valid certification path to requested target...... 网上很多的解决方式是更新站点的地址,我这里修改了一个日本的地址(清华镜像也好),其实发现是解决不了上述的报错问题的,其实,最终拉去插件的时候,会提示证书的问题,几经周折找到了其中一遍博文