首页 > 其他分享 >设计模式

设计模式

时间:2023-03-01 16:44:42浏览次数:28  
标签:功能 原则 模式 接口 模块 内聚 设计模式

设计模式

构成

设计模式由原则和方法两部分组成,原则代表了基本思路,而方式则是其的具体实现。另外设计模式是一种经验主义,所以重在理解而非模仿,以此思考并因地制宜的做出决策才是最佳的用法。

  • 原则
    这是必须要记住的内容,但要注意的是原则是一种思想,仅靠死记硬背一点用都没有,必须要真正理解后才能使用。
  • 方法
    方法在各个不同的开发环境中可能会有所区别,所以仅是一种参考,具体还需要配合相关原则因地制宜的使用,若不知其意却强行装模做样结果只会东施效颦。而且只要真正理解了设计原则,并且对编程语言足够熟悉的话,设计方法是可以自己推导出来的。所以若是特意要去背着玩意我觉得有点吃力不讨好。

目标

设计原则之间是相关的,是可以逐步推导出来的,因为其最终目的都是为实现“高内聚,低耦合”,实现这一目的就要求功能“模块化”。模块化的基本设计思路是“单项依赖,逐层精化”,将其放置到具体的面对对象编程中便引出了名为“设计模式”的软件开发方式。

  • 模块化
    将程序中的所有功能划分为一个一个相互独立不可分割的功能部件。其中模块内的功能特定又集中,具有着内聚的特性。而模块间则基本独立无关,但也可能存在着少量的依赖关系,这便又拥有着耦合的特性。一个优秀的模块化设计应尽可能做到“模块中高内聚,模块间低耦合”。
  • 在模块中高内聚
    若你开始使用诸如大段复制粘贴之类的方式编写程序,那你的程序恐怕就没有实现高内聚。内聚代表着强关联性,比如去掉某模块中的一个函数,则可能整个模块都会无法运行,因为其中的每个函数间相互关联相互依赖的。
  • 在模块间低耦合
    耦合代表着存在依赖关系,如去掉模块A,模块B则无法使用,说明B模块依赖于A模块。若去掉B模块,A模块也无法运行,则代表着A和B存在着双向依赖,这种情况应该避免。利用接口事件等方式将其调整为单向依赖,否则考虑将其合并为同一个模块
    允许模块间依赖,但应该尽可能减少这种关系。模块之间应尽可能不相关不依赖,如去掉某模块,程序可能会缺失部分功能但大部分功能应该依然能正常运行。这样不仅程序出错的概率被降低,而且通用性强移植性好,也便于团队协作。
  • 平衡内聚和耦合
    模块化中的内聚和耦合是相互制衡的关系,模块的高内聚必然会导致模块间低耦合,反之同理。为了让软件开发更加便捷更加健壮,我们当然希望程序能尽可能的做到高内聚,但过于极端的追求会导致模块数量激增,项目变的过于复杂度,开发成本过高从而导致结果也适得其反。所以高内聚究竟要达到什么水平,这是一个权重值,需要根据具体场景进行调整,建议依据哈夫曼压缩原理进行决策。
  • 单向依赖与逐层精化
    上述有关耦合的描述中已经说明了一些有关单向依赖的问题,无法做到单向依赖会导致功能调整变得复杂且困难,项目的结构最终也会变成难以理解的网状。理想的项目结构应该类似树形拥有明显的层次关系。
    从开发者的角度,我们知道一个模块可能要依赖于其他模块才能运行,但这对使用者来说却可能是透明的,因为每个模块都代表一种独立的功能,这就要求它最终要把这种依赖关系转变成封装关系,这也是为什么项目会产生层次性的原因。每一层都是对下层内容的封装,反过来每一层又都是对上层内容的细化,这便是逐层精华的由来。

设计原则

为实现上述目标,设计模式提出了7点基本原则,网上也有说6点的,主要是因为“单一职责原则”和“接口隔离原则”可以理解为同一原则,不过下述还是归类为7点,但不做细致讲解。

根本问题

  • 开闭原则

    如何以扩展的方式调整功能而不是直接对源代码进行修改?

    一个程序需要拥有很好的适应性才能应对各种需求,因此应该具备扩展原有功能的能力,但这种扩展功能的方式不应该是直接修改原代码。
    每一次修改代码都可能导致出错,若为一个新功能而修改代码,结果往往是得不偿失导致旧功能因此受牵连出问题,而且这种方式对团队协作也很不友好。
    那么如何在不修改原代码的前提下实现功能扩展呢?由此引出了下述原则。

如何解决

  • 里氏替换原则

    通过实现“接口”来完成功能扩展(此接口非彼接口!)

    确保任何基类可以出现的地方,子类一定可以出现,用派生类替换基类时,原功能应不受影响。这样扩展功能时就可以利用继承重写的方式,实现开闭原则。
    该条其实不单单是指接口和继承,包括委托事件这些都应该算在类,因为它们有一个共同特点就是都有将算法的一部分参数化的功能。
    但为何只提到了继承和接口呢?如果使用的是java很容易理解了,因为java中不存在委托类型,所以到处使用的都只有接口和匿名类。

    实现细节

    • 依赖倒转原则:

      通过里氏代换原则的指导,我们要学会一种全新的编程方式,面向接口编程。如果某功能存在扩展的需求,那我们应当将这部分代码接口化,从而隐藏具体细节,让功能依赖于接口而非实现。
      因为实现不再被依赖,所以它可以成为一个独立自由的个体,我们可以很方便很安全的进行开发和修改,且不会干扰到原有模块。

    • 接口隔离原则

      面向接口编程时,在设计上应尽可能保证提供多个相互独立的接口,而非臃肿的一整块,这可以减少耦合性,不然这些接口反而会成为累赘,逼着别人违反单一职责原则。

  • 开闭原则中的扩展

    通过组合多个模块来完成功能扩展

    扩展意味着原功能依旧保持独立,这不单单是指代码上的修改,这里其实还隐藏着开闭原则对功能模块化的要求。

    • 单一职责原则:

      每个模块都应该仅负责少量且专精的功能,这是模块化中对高内聚的基本要求,不多赘述。

    • 最少知道原则(迪米特原则):

      一个模块应尽可能减少对其他模块的使用,使系统功能相对独立,这是模块化中对低耦合的基本要求,也不多赘述。

  • 合成复用原则

    里氏替换原则中主要讲述了有关面向接口的编程方案,这种方式是利用了继承的特性。继承仍然会产生耦合性,比如子类将无法摆脱父类而存在,再加上一些语言特性和开发框架等影响,实际用起来很可能会出现水土不服的影响。
    这时开闭原则对模块化的要求给我们带来了另一种解决方案“组合”,组合是直接通过增设更多的功能模块从而实现功能的扩展,它不受一些继承问题带来的限制,而且产生的耦合性也小的多。其实这也是早期软件开发的常见方式,毕竟一开始没有面向对象编程。
    这两种方案都各有优势,各有适合的场景,因地制宜,取长补短,相辅相成便能实现一加一大于二的效果,而这也正是开发软件的正确姿势。

具体例子

Unity框架中,所有碰撞体都继承了Collider类,通过里氏替换原则,子类得以可以自由扩展功能,且Unity还不需要做任何额外工作,一套旧代码就能处理任何新子类。
不同碰撞体间的差异需求导致产生了诸如BoxCollider,SphereCollider等子类,这些子类符合单一职责原则和最少知道原则,仅额外简单的实现了些形状上的差异,所以开发和使用时也不会相互影响。
但一个刚体往往需要的形状是非常复杂的,上述这些碰撞体由于过于简单都无法满足需求,此时Unity便采用组合的方式,将不同碰撞体的功能合并起来聚沙成塔,这样不需要写任何代码就能随意搭配出各种自己想要的碰撞形状来。

如果不采用上述方案,那每一个子类都要单独写处理的代码,每一个新需求又会导致要重新写一个新子类,一两个还好,要是几十几百个,妈耶,累死。结果刚写完,项目经理跑过来说,旧的需求要改一下......
不用想了,这下肯定得有一个人要进医院。

设计方法

累了不写了,我直接复制粘贴,以后再看。
创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式(7):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式(11):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

标签:功能,原则,模式,接口,模块,内聚,设计模式
From: https://www.cnblogs.com/BDFFZI/p/17168797.html

相关文章

  • 设计模式 策略模式
    案例背景如果一个项目需求游戏设计一个武士 可以使用的武器有刀枪弓箭并且可以随时切换使用那么我们这个程序要怎么写?我们可以写成这样 这个代码也能实现功能......
  • 23种设计模式一:单例模式
    1、说明1.1定义单例模式(SingletonPattern)是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的......
  • 设计模式&业务场景
    目录单例工厂观察者模板方法责任链策略单例工厂观察者模板方法责任链策略......
  • 单例设计模式
    单例模式:定义:某个类在某个系统中只能有一个实例化对象被获取和使用实现要点:1.构造器私有2.含有一个该类的静态变量保存这个唯一实例3.对外提供获取该实例对象的方式......
  • 设计模式(十二)----结构型模式之代理模式和装饰者模式的区别
    1、代理和装饰者的区别静态代理和装饰者模式的区别:相同点:都要实现与目标类相同的业务接口在两个类中都要声明目标对象都可以在不修改目标类的前提下增强目标......
  • 设计模式(十三)----结构型模式之桥接模式
    1概述现在有一个需求,需要创建不同的图形,并且每个图形都有可能会有不同的颜色。我们可以利用继承的方式来设计类的关系:我们可以发现有很多的类,假如我们再增加一个形状或......
  • 设计模式:创建型
    简单工厂模式1publicinterfaceComputer{23voidsetComputerSystem();45}67publicclassXiaoMiComputerimplementsComputer{89......
  • 模板设计模式
    1、什么是模板设计模式把抽象类(AbstractClass)整体看作是一个模板,模板中不能决定的东西定义成抽象方法(AbstractMethod),让继承的子类去重写抽象方法实现需求。2、使用......
  • 代理设计模式还不会?2分钟搞定
    概述代理模式就是给某一个对象提供一个代理,并由代理对象控制对原对象的引用。在一些情况下,一个客户不想或者不能直接引用一个对象,而代理对象可以在客户端和目标对象之间起......
  • 03_16_JavaWeb||day19_Filter&Listener||day19_Filter&代理模式(23种设计模式之一:用来
    今日内容*Servlet,Filter,Listener被称为JavaWeb三大组件1.Filter:过滤器2.Listener:监听器1.Filter:过滤器概念:生活中的过滤器:净水器,空气净化器,土匪、web中的过滤器:当......