软件设计模式总述

 

# 背景
      1990年,软件开发设计模式萌芽。
      1995年,《设计模式:可复用面向对象软件的基础》(Gang of Four,简称GoF,匿名著作)的出版,奠定了软件设计模式的基础。里面收录的23种设计模式,更是直到今天还在大范围被研究、讨论、运用。
      此次关于设计模式的系列文章,所研究和讨论的就是上述的GoF的23种设计模式。
   

# 概念
    软件设计模式:又称设计模式,简单来说,是一种代码设计经验的总结,是解决特定问题的套路,具有普遍性,可反复使用,可以提高代码的可重用性、代码的可读性和可靠性。

#  意义
    设计模式的本质是面向对象设计原则(后面会有专门的论述)的实际运用,是对类的封装性,继承性,多态性以及类的关联关系、组合关系的充分理解。
    
    利用现有的、已证明成功的设计模式来设计软件架构,使得软件设计更加的标准化,提高开发的效率,减少软件设计风险,使得代码的可重用性高,可读性强,可靠性高(当然并不是所有的设计模式都能达到这些效果,恰当的场景,恰当的使用才是关键)。
    
    软件设计过程中,直接思考现有业务场景适合哪些设计模式(设计模式一般都不是单独使用的,多个设计模式的综合使用,才更加能够发挥出设计模式的优势),用现有设计模式来完成架构设计,大大缩减了架构设计的时间,也避免了自行设计过程中,由于考虑不周,不成熟可能产生的各种问题。由于大家都对现有设计模式比较熟悉(即使还不熟悉,也有大量的现有资料可查),显著减少了沟通成本,自己写的代码,即使过了一年半载,根据设计模式一回忆,能够迅速拾起回忆,即使是阅读他人的代码,也不至于不知所云。
    
    但是也不能因为设计模式有如上的诸多好处,就乱套、乱用,正确使用设计模式才能使得设计模式发挥出真正的作用,体现出价值。在具体的软件开发过程中,必须根据当前系统的特点来恰当选择,甚至当系统功能比较简单的时候,不引入设计模式才是最好的选择,引用设计模式反而会大大增加了系统的复杂性。

#  分类
       按照不同的分类标准,设计可能会有多种划分标准,本文中特指按照设计模式的工作内容或者说目的来划分,主要有以下三种:
       
      1、创建型模式
      
             创建型模式,将对象的创建和使用分离,试图根据具体的情况使用合适的方式来创建对象,并将具体对象的创建过程封装隐藏起来。可以分为类创建型模式(处理类的创建,将对象的创建推迟到它的子类中)和对象创建模式(处理对象的创建,将对象创建的一部分推迟到另一个对象中)。
             
             创建型模式包括:
             
              (1)单例模式
              
                       单例模式可以说是所有设计模式中最简单的一个,使用率也很高,简单来说,就是通过某种手段保证整个系统应用中有且仅有一个实例,需要使用时,调用已知的某个公用方法即可获取。
                       
               (2)工厂方法模式
               
                      工厂方法模式一般是负责一个系列对象的创建,工厂中定义一系列的标准,但并不具体创建对象,具体创建对象的行为由下面实现了这个工厂标准的具体子工厂来完成。
                      
               (3)抽象工厂模式
               
                     抽象工厂模式相对于工厂方法模式来说,可以说是负责几个系列对象的创建,抽象工厂内部将几个系列的对象分隔开来,是对上面工厂方法模式的进一步抽象,具体对象创建还是要分派到每一个系列对象的指定工厂里面。
                     
               (4) 原型模式
               
                      原型模式是用一个对象来创建一个新的对象,不是通过传统的new的方式来创建,而是通过拷贝的方式来实现,可以参考Object里面提供的clone方法。
                      
                (5) 建造者模式
                      
                        建造者模式一般用来创建比较复杂的对象,对象可能有多个组成部分,并且有多个装配方式,通过与二者相分离的算法相结合来建造不同的对象。
                
       2、结构型模式
       
              结构性模式,分为类结构模式(通过集成类或者接口方式)和对象结构模型(通过组合或者聚合方式),试图将类或者对象按照某种方式变成一个更大的结构。
              
               结构型模式包括:
               
               (1) 代理模式
               
                         代理模式,如同它的名称所示,会为某个具体处理业务的对象生成一个代理对象,所有需要与该业务对象有交集的操作,都是通过代理对象来完成。代理对象可以有自己的功能逻辑,来作为对原业务对象功能的增强,也可以看成对原业务对象访问的一种控制,当需要原业务对象的功能时,由代理对象来对原业务对象功能进行调用完成具体的业务逻辑。
                         
               (2)适配器模式
                      
                      适配器模式,就是将原本与功能不相配的对象、类,通过某种包装(组合/聚合、继承),使之变得相配的一种模式。
                                     
               (3)桥接模式
                   
                        桥接模式,就是将某个抽象和它的具体实现之间的关系由强关联变成弱关联,解除彼此之间的耦合,使得可以各自变化。
                   
               (4)装饰器模式
                        
                        装饰器模式,是指在不改变原有类的基础上,为其添加一层包装,来实现额外的功能。

               (5)享元模式
               
                        享元模式,是指某些类中都有某个相同的结构,为了不重复创建,就将这个相同的结构提取出来单独形成一个外部数据结构,当这些类需要的时候,再分别调用即可。

               (6)外观模式

                       外观模式,又可以称为门面模式,是指将完成某个具体复杂功能的子功能都包装成一个统一的大功能,以一个统一的外观对外提供服务,客户端不需要关心这个外观里面是怎么具体工作的,只需要调用服务,即可实现功能。

               (7)组合模式

                     组合模式,也可以称为部分、整体模式,它是用来解决树形结构的数据处理,树形结构里面有简单元素,也有复杂元素,通过组合模式,可以使得在使用过程中,不需要区分简单元素还是复杂元素,统一用一个方式去处理即可。
               
      3、行为型模式
      
            行为型模式,分为类行为模式(采用集成机制在类间分派行为)和对象行为模式(采用组合或者聚合的方式在对象间分派行为),行为型模式关注点不仅仅在类和对象的结构上面,更重要的是解决实体之间的通行关系。
            
            结构型模式包括:
            
            (1)模板方法模式
                    
                    模板方法模式,是指在超类、接口中形成一个抽象模板,每个符合该模板的具体业务,都需要继承或者实现该模板,为某些方法提供具体的算法逻辑,并且可以改变一部分方法步骤,来完成具体的业务逻辑。

            (2)策略模式

                   策略模式,是指将业务场景中的针对某一行为的算法,抽象出来,再按照场景形成一个个的具体而完整的策略,在运行中动态的选择具体策略,不同的策略之间可以相互替换。
                   
           (3)命令模式
                    
                    命令模式,是指将请求和实现两者分开,各自变化,中间添加一个协调人,针对不同的请求发出不同的命令给到实现者,完成具体的请求工作内容。
          
           (4)责任链模式
                   
                   责任链模式,是指将一系列的对象用链条串起来,每个对象都指明它的下家,请求在这个链条上游走,直到找到能处理请求的一个。

           (5)状态模式
                
                    状态模式,是指一个对象的内容有个状态标识,而不同的状态值会引起不同的行为。

           (6)观察者模式
                   
                   观察者模式中有一个一对多的对象关系,当一的对象发生改变时,会发出通知到上述的多个对象,这些对象收到通知后,会做出一些响应。
                    

           (7)中介者模式
                            
                    中介者模式,是指将多个互相引用关系的对象之间的引用关系抽离出来,放在一个中介对象里面,使得前述多个对象可以不在显式的互相引用,已达到松耦合,便于扩展的目的。
                    
           (8)迭代器模式

                   迭代器模式,一种非常常用的设计模式,文艺点的说法是,以某种顺序依次访问某个聚合对象的内部元素,通俗的说法就是遍历。

           (9)访问者模式

                   访问者模式,相对来说比较复杂,很难几句话交代清楚,主要的逻辑是说,在不改变某个对象中的元素的前提下,可以增加作用于元素的行为。

          (10)备忘录模式

                   备忘录模式,如其名,相当于创建一个备忘录,将某个对象的状态保存在其中,以便后期需要时可以恢复该对象的历史状态。

          (11)解释器模式
                    
                    解释器模式,基本很少使用到,某种程度上来说相当于又定义了一种语言。粗略来说,就相当于给定一些符号及这些符号对应的语义,然后生成一套解析逻辑,可以参考正则表达式,cron表达式等。
          
#  面向对象的设计原则
        前面在设计模式的意义模块有提到过,设计模式是对面向对象设计原则的实际应用,因此,正确理解以下七个原则对进一步深入理解和运用设计模式有着重要的作用和意义。
       
       首先写在前面的是,以下这些设计原则是我们开发的指导性原则,如果能够做到对系统设计会提供诸多便利,但是这些并不是强制性要求,一定不能违反,在某些特定的情况下,如果违反某些少部分原则能够更好的实现功能,获取更好的性能等前提下,也是可以不完全遵循以下原则的。就上述已经成型的23种设计模式来说,也并不是每个都完全遵循了这七个设计原则。
       
       不管是设计原则也好、设计模式也好,死记硬背,生搬硬套不是目的,能够灵活的运用,化有形于无形更好的为系统为项目服务才是目的。
   
      但是不管目的是什么,理解、记忆并且模拟着使用都是迈向熟练掌握的第一步。
     
       1、开闭原则
            
            开闭原则,一句话就是对扩展打开,对修改关闭,意思就是需要程序能够在不修改源代码的前提下,进行功能扩充。这个原则的好处显而易见,如果对已经成型甚至已经上线的代码进行修改,稍有不慎,就会改出新的问题,而且修改过程中,为了减少修改的范围及影响,往往会采用一些贴补式写法,容易造成代码冗余,逻辑复杂,可读性比较差等问题。修改过的代码还需要重新进行全量的代码测试,增加了开发测试时间成本。
            要做到这个原则并不容易,需要我们对每次的需求场景做全面长远的分析,保证设计方案有利于后期的进一步扩展。
            
        2、里氏替换原则
              
              里氏替换原则,指导性思想就是所有父类出现的地方,子类都可以对它进行替换,并且不影响正常的功能。怎么才能做到这一点,用通俗的话讲,就是子类能够分别实现父类的抽象方法,但是对于父类已经提供实现的方法,就尽量不要再重写了。这个规定主要是为了保证继承体系的可复用性,减少由于运用多态而出现的程序运行出错或者效果偏离的问题。
              这个原则主要是对继承体系的一个规范,原本的继承设计中,如果某些情况下可能会违反这个原则,就要考虑下,此处是否一定要采用继承才能达到最好的效果,如果答案是否定的,可以尝试取消继承,并重新设计它们之间的关系。

        3、依赖倒置原则
        
            依赖倒置原则,说的是在代码编写过程中,调用“抽象”,而不要调用‘’具体‘’,总的来说就是要面向接口编程,由于"抽象"变动的可能性会比较小,具体的实现逻辑可能会多种多样并且面临频繁修改的可能性,如果调用的"具体","具体"的逻辑变了,就可能会导致调用方也一并要修改。这样就会导致系统不稳定,接口之间的耦合性比较深。

        4、迪米特法则
   
             迪米特法则,是一个叫迪米特的人提出来的,简单的总结成一句话,就是‘’‘不要和陌生人说话’。哪些算是陌生人呢,除了当前对象、当前对象的成员对象,当前类的方法参数,当前类所创建的对象等与当前类有着具体直接、间接关系的类之外的其他不相关对象。
             这些类在设计的过程中,尽量保证高内聚,细节都写在类的内部,不要漏出来给别人知道,以免彼此之间细节依赖太深,耦合在一起,牵一发而动全身。
             而陌生对象之间的调用就通过一个与两者都有关联的第三方中介类。但是中介类过多,也会造成系统复杂性上升,模块之间的通信效率低等问题,所以这就需要在软件设计的时候保持一个平衡,在系统结构清晰的前提下,对类尽量的保持高内聚,低耦合,该隐藏的隐藏,该暴露的暴露。

        5、单一职责原则

             单一职责原则,一句话来说就是“一个人只能负责一件事”。这个原则说起来简单,做起来却并不简单,首先需要能够清晰准确的对职责进行划分,分别将职责存放在不同的类中,可以减少职责之间的相关干扰,调用的时候,也会避免了打包赠送不需要的职责,减少了代码冗余。

        6、接口隔离原则
      
            接口隔离原则,又叫接口最小化原则,意思就是一个接口里面设计的功能应该尽可能的少,避免别人为了实现你的某一个功能,还得接收其他不需要的功能。对外提供服务的时候,又会造成一种假象,以为其他功能也是可以调用的,结果里面并没有相关实现。
      
        7、合成复用原则
             
             合成复用原则,又叫组合、聚合原则,中心思想就是减少继承,优先使用组合、聚合方式组织对象,如果要使用继承,就应该严格遵守迪米特法则。
           

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值