Skip to content

hansonboy/DesignPattern

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

#####UML图示表示

  1. 依赖关系:A------->B B作为A的方法调用参数
  2. 关联关系:A———————>B B作为A的成员变量使用(暗示两个类在概念上位于相同的级别)
  3. 聚合关系:A<>—————>B B作为A的成员变量使用(整体/局部关系,暗示着整体在概念上处于比局部更高的一个级别)
  4. 合成关系:A♦️——-——>B B作为A的成员变量使用(整体要么负责保持局部的存活状态,要么负责将其销毁。局部不可与其他整体共享)
  5. 继承关系:A———————1> B A作为B的子类
  6. 实现关系:A-------1> B A实现了接口B
一句话简单描述设计模式六大原则
  1. 尽可能抽象,逻辑抽取,方便复用,代码的自定义(单一责任原则)

  2. 依赖于抽象接口协议,而不要依赖于具体的类(依赖倒置原则)

  3. 子类可以完全替换父类的功能(里氏替换原则)

  4. 开放的需求通过新增代码实现,新功能可以扩展,修改需求则只需要修改自己的代码就可以了,不会扩散。(开放封闭原则)

  5. 面向最小接口编程,以免接口臃肿(接口隔离原则)

  6. 最少知识原则,只和朋友类进行交互,方法内不要使用非朋友类,朋友类指的是:出现在成员变量,方法输入输出参数中的类,和朋友类保持距离,保护自己的隐私,减少类间交互(迪米特法则)

  7. 最小类原则,防止类由于继承而变得臃肿,尽量使用合成、聚合,不要使用类继承(合成复用原则)

  8. 合成一句话就是:设计模式总的原则就是让合适的代码放到合适的位置方便复用,减少代码冗余。解耦合就用接口加继承(依赖倒置-开闭原则),具体类接口怎么写(单一责任原则,接口隔离原则),如何写子类(里氏替换原则),类间如何交互(最小知识原则)请看下面你的具体设计模式。

#####设计模式

  1. 适配器模式

    1. 定义

      适配器模式是指,将一个类的接口转换为客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
      
    2. 结构图

      分为类适配器模式和对象适配器模式两种,类适配器模式是通过多继承来实现的,对象适配器模式则很像是代理模式。
      
    3. 何时使用

      1.	一般是属于事后补救时候使用,接口调用方和被调用方接口都不能修改情况下,为了实现复用该功能一致但接口不同的代码,我们使用适配器
      2.	适配器模式还用在封装第三方接口上面,因为我们不希望我们的系统接口随着外部的第三方接口改变而改变,此时我们就是用适配器模式
      
    4. 区别于代理模式

      相同点:都是将被调用方作为属性来使用
      不同点:
      	1. 适配器中的的代理是已经实现的实体类,不是接口,适配器模式需要适配器继承调用方,然后在调用方接口函数中调用该代理方法
      	2. 代理模式中的代理在委托中是一个接口,我们不知道代理会具体做什么,但是知道代理的调用时机,我们使用的时候主要是继承代理接口成为代理,然后在代理方法中做我们想做的事情。
      
  2. 简单工厂模式

    1. 定义

       用一个类来封装子类实例的初始化操作
      
    2. 结构图

    3. 何时使用 1. 重复调用初始化操作的时候,减轻用户的初始化负担 2. 重复调用一些事先可以确定的初始化操作,那么可以放到工厂类中

  3. 策略模式

    1. 定义

       策略模式:定义了算法家族,分别用子类封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到算法的客户。
      
    2. 结构图

    3. 何时使用 1. 封装不同的算法或者是不同的业务规则 2. 减少算法类和算法调用类之间的耦合

    4. 优点: 1. 方便进行单元测试,每个算法都有自己的接口类,可以通过自己的接口来单独进行测试

  4. 装饰模式

    1. 定义

       装饰模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
      
    2. 结构图

    3. 何时使用

      1.使用时机:见模式定义
      2.实现原理:通过SetComponent 来对对象进行包装,每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中
      
    4. 个人理解

      有点像链表哦,所有的装饰都可以放入到链表的节点中,然后最后的装饰节点输出会递归的返回上一个节点的输出,这样就给对象增加了不同顺序的功能。	
      
  5. 代理模式

    1. 定义

      代理模式:将自己想做的事情定义一个借口委托给别人代理实现,然后自己拥有这个对象,想让他在什么时候调用什么方法就在什么时候调用什么方法,当然该方法具体做什么还是由代理来决定的。
      
    2. 结构图

    3. 何时使用

       1.委托方知道事件的调用时机,但是不知道具体执行的操作
      
  6. 工厂方法模式(满足开放封闭原则)

    1. 定义

       工厂方法模式:定义一个用于创建对象的接口,让子类来决定实例化哪一个类。工厂方法使一个类的实例化延迟到了子类。
      
    2. 结构图

    3. 简单工厂模式VS工厂方法模式

      -简单工厂模式:最大的优点是工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关类,对于客户端来说,去除了与具体产品类名的依赖,但是违反了开放-封闭原则。
      -工厂方法模式:客户端需要决定实例化哪一个工厂来实现产品,选择判断的问题还是存在的,也就是说,工厂方法吧简单工厂的内部逻辑判断移到了客户端代码来进行,想要增加产品,本来是修改简单工厂模式内部代码的,现在变成了修改客户端代码,但是满足了开放-封闭原则。
      
  7. 原型模式

    1. 定义

       原型模式: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
      
    2. 结构图

    3. 理解

       -原型模式其实就是从一个对象创建出另外一个可以定制的对象,而且不需要知道任何创建的细节。实现一个clone接口就可以了
       -要注意浅拷贝和深拷贝的区别,看我们是要用哪一种,当我们需要修改一次就可以修改对个副本时候,我们使用浅拷贝,当我们希望每一个副本都可以修改为不同的对象属性的时候,我们使用深拷贝。
      
  8. 模板方法模式

    1. 定义

       模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
      
    2. 结构图

    3. 模板方法模式的特点:

       -通过把不变的行为搬移到父类中,去除了子类中的重复代码来体现它的优势
       -当不变和可变行为在方法的子类实现中混合在一起的时候,不变行为的在子类重复出现。我们通过模板方法模式把这些行为搬移到一个单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。
      
  9. 外观模式

    1. 定义

       -外观模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层的接口,这个接口是的这一子系统更加容易使用。
       -外观模式知道哪些子类负责处理请求,将客户的请求代理给适当的子系统对象
      
    2. 结构图

    3. 何时使用

       -在设计初期,应该要有意识的将不同的两个层分离 ,层与层之间建立外观模式
       -在开发阶段,子系统因为不断的重构演化而变得越来越复杂,增加外观模式可以提供一个简单的接口,减少他们之间的依赖。
       -在维护一个遗留的大型系统时,可能这个系统已经非常难于维护和扩展了,此时可以为新系统开发一个外观类,来提供设计粗糙或高度复杂的遗留代码的比较清晰的接口,让新系统与外观类对象交互,Facade 与遗留代码交互所有复杂的工作。
      
    4. 外观模式 VS 适配器模式

       -适配器模式:面向接口			
       -外观模式:面向子系统,符合迪米特原则
      
  10. 建造者模式

    1. 定义

      建造者模式:将一个复杂对象的构建与它的表示分离,是的同样的构建过程可以创建不同的表示。
      
    2. 结构图

    3. 特点:

      -将一个复杂对象的构建与它的表示分离,使得同样的构造过程可以创建不同的表示
      -如果我们使用了建造者模式,那么用户只需要指定需要建造的类型就可以得到他们,而具体的建造的过程和细节就不需要知道了。
      -Builder :为创建一个Product对象的各个部件指定的抽象接口。
      -ConcreteBuilder: 具体的建造者,实现了Builder接口,构造和装配各个部件。
      -Product: 具体的产品角色
      -Director: 指挥者,用来根据用户的需求创建不同的小人对象
      
    4. 何时使用

      -主要用来创建一些比较复杂的对象,这些对象内部构建间的建造顺序通常是固定的,但是对象内部的构建通常面临着复杂的变化。
      -建造者模式的好处是:使得建造代码和表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。
      
  11. 观察者模式

    1. 定义

      观察者模式:定义了一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化的时候,会通知所有的观察者对象,使他们能够自动更新自己。
      
    2. 结构图

    3. 何时使用

      -将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就需要维护相关对象之间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护,扩展和重用都带来不便。
      -当一个对象的改变需要同时改变其他对象的时候,而且不知道有多少对象有待改变
      -观察者模式所做的事情是在解耦合,让耦合的双方都依赖于抽象而不是依赖于具体,从而使得各自的变化都不影响另一边的变化
      
    4. 委托事件

       -观察者模式有个缺点: 通知者要在自己的通知方法中遍历所有的观察者,然后调用这些对象相同的方法,实际情况中可能这些对象想要执行的方法并没有相同的函数名字
       -使用委托:委托一种引用方法的类型。一旦为委托分配了方法,那么委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值,委托可以看做是对函数的抽象,是函数的‘类’,委托的实例将代表一个具体的函数。
       -一个委托可以搭载多个方法,所有的方法将会被依次唤醒。
       -可以使得委托对象所搭载的方法并不属于同一个类。
       -委托对象所搭载的方法必须具有相同的原形和形式,也就是有相同的参数列表和返回值类型。
      
  12. 抽象工厂模式

    1. 定义

      抽象工厂模式:提供一个创建一系列或相互依赖对象的即可欧,而无需指定他们具体的类。
      
    2. 结构图

    3. 何时使用

       当只有一个产品系列的时候只需要使用工厂方法模式就足够了,但是如果有多个产品系的时候,需要使用抽象工厂模式。
      
    4. 优点

       - 是易于交换产品系列,由于具体工厂类在一个应用中代表着从产品系,只需要初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,他只需要改变具体的工厂就可以使用不同的产品配置。
       - 让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
       - 增加新的产品系列的时候比较方便,只需要增加一个具体的子类Factory 就可以了
      
    5. 缺点

      - 当增加新的功能(产品)的时候,我们需要修改Factory 接口以及具体的Factory实现来满足我们的要求,不满足封闭性原则。
      
    6. 改进

      -使用简单工厂模式可以有效改善增加新的产品的问题,这时我们只需要添加产品,然后在简单工厂里面添加case 语句就可以了。
      -再进一步,使用反射可以去除掉case语句,只需要修改对应的类名字符串就可以了。此时的字符串如果是定义在工厂内部的,那么可以使用配置文件来配置,然后让该字段读取该配置文件来解决;当然也可以放在参数里面,由调用方决定使用哪一个,但是这样可能会更改很多次哦。
      
  13. 状态模式

    1. 定义

      状态模式:当一个对象的内在状态发生了改变时,允许改变其行为,这个对象看起来像是改变了其类。
      
    2. 结构图

    3. 何时使用

      -状态模式:主要解决的是当控制一个对象状态转换条件的条件表达式过于复杂时的情况。把状态的判条件转移到表示不同状态的一些列类当中,可以把复杂的判断逻辑简化。
      
    4. 优点(类似于活字印刷术的出现)

       - 将于特定状态相关的行为局部化,并且将不同的状态的行为分割开来
       - 将特定的状态相关的行为放到一个对象中,由于所有与状态相关的代码都存在于某一个ConcereateState 中,所以通过定义新的子类可以很容易地增加新的状态和转换。
       -消除庞大的条件分支语句,状态模式通过将各种状态转移逻辑分布到state的子类中,来减少相互间的依赖。 好比把整个版面又改成一个一个活字了	
      
  14. 备忘录模式

    1. 定义

       备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
      
    2. 结构图

       - Originator(发起人): 负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录来恢复内部的状态。Originator 可根据需求决定Memoto 存储Originator 的哪些内部状态
       - Memeto(备忘录):负责存储Originator 对象的内部状态,并可防止Originator 以外的其他对象访问备忘录Memento. 备忘录有两个接口,Caretaker 只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator 可以看到一个宽接口,允许它访问返回到之前状态所需的所有数据。
       - CareTaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。
      
    3. 何时使用及优点

      • 把要保存的细节全部封装在Memento 中,客户端在保存和恢复的过程中不需要了解这些细节了
      • Memonto 模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性知识众多属性中的一小部分。
    4. 缺点

      角色状态信息要完整的保存在备忘录对象中,如果数据太多,会很占内存。		
      
  15. 迭代器模式 1. 定义

       迭代器模式:提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象内部表示
    
2. 结构图
3. 何时使用
		
		1. 当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,你就应该考虑使用迭代器模式。
		2. 当需要对聚集有多种方式遍历时,可以考虑使用迭代器模式
		3. 为遍历不同的聚集结构提供如开始,下一个,是否结束,当前那一项等统一接口
		4. foreach in 的使用:本质就是使用的迭代器模式
4. 特点
		
		迭代器模式分离了集合对象的遍历行为,抽象出一个迭代器来负责,这样既可以做到不暴露集合内部的结构(内部的变量,不关你是张三还是李四),又可以让外部的代码透明的访问集合内部的数据。
5. 售票员买票的过程
  1. 单例模式 1. 定义

       单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
    
2. 结构图
3. 分类
		
		- 饿汉式单例模式:使用了静态初始化方法,在类加载的时候就进行了初始化。
		- 懒汉式单例模式:使用了双重锁机制来保证多线程安全,用的时候才初始化
4. 与工具类方法的区别: 在于单例模式有自己的状态,但是工具类一般都是方法的集合,内部没有状态。
  1. 桥接模式 1. 定义

       桥接模式:将抽象部分与他的实现部分分离,使他们能够独立变化。
       实现指的是抽象类和它的派生类用来实现自己的对象。实现系统可能有多个角度的分类,每一种分类都有可能变化,那么就把这种多角度分离出来让他们独立成类,独立变化,减少了他们之间的耦合
    
2.	结构图
  1. 命令模式 1. 定义 命令模式:将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。 2. 结构图 3. 作用

       - 能较容易的实现命令队列
       - 在需要的情况下,可以较容易的将命令记录到日志
       - 允许接受请求的一方决定是否要否决请求
       - 可以容易地实现对请求的撤销和重做
       - 由于加进新的具体命令类不影响其他类,所以很容易添加新的命令
       - 命名模式将请求一个操作的对象与知道怎么执行一个操作的对象分隔开了
    
  2. 职责链模式 1. 定义

       职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
    
2. 结构图
3.  特点
		
		- 当客户提交一个请求时,请求是沿着链传递直至有一个ConcreteHandler 对象负责处理它。
		- 接收者和发送者都没有对方明确的信息,且链条中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需保持一个指向其后继者的引用,而不需要保存所有的候选接收者的引用
		- 随时增加或者修改处理一个请求的结构是方便的,增加了给对象指派职责的灵活性。
		- 一个请求极有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理
4. 职责链模式VS组合模式
  1. 中介者模式

    1. 定义

       中介者模式:用一个中介对象来封装一系列的对象的交互。中介者使各对象不需要显示的相互引用,从而使其耦合松散,而且可以独立的改变他们之间的交互。
       出现的原因: 尽管当一个系统分割成多个对象通常可以增加其可复用性,但是对象间的相互连接的激增又会降低其可复用性。大量的连接使得一个对象不可能在没有其他对象的支持下工作,系统表现为一个不可分割的整体,所以对系统的行为进行任何较大的改动就十分困难了。符合迪米特法则。能够不直接发生作用,就不要直接发生作用,让第三方去转发这个作用过程
       - 具体中介对象:实现抽象中介的方法,他需要知道所有具体同事类,并从具体同事接受消息,向具体同事对象发出命令
       - 具体同事类:每个具体同时类只知道自己的行为,不了解其他同事类的情况,但是他们都认识中介者对象
      
    2. 结构图

    3. 优缺点

       - 终结者模式很容易在系统中应用,也很容易在系统中误用,当系统出现了多对多的交互复杂的对象群的时,不要急于使用中介者模式,而要反思你的系统在设计上是不是合理。
       - 中介者者模式一般应用于一组对象以定义良好但是以复杂的方式进行通信的场合,以及想要定制一个分布在多个类中的行为,而又不想生成太多的子类的场合。
      
  2. 享元模式

    1. 定义

       享元模式:运用共享技术有效地支持大量细粒度的对象。
      
    2. 结构图

    3. 内部状态和外部状态

      -在享元模式对象内部并且不会随着环境改变而改变的共享部分,可以称为是享元对象的内部状态
      -随着环境改变而改变,不可以共享的状态就是外部状态。
      
    4. 享元模式的优点:

      - 享元模式可以避免大量非常相似类的开销。
      - 在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果发现这些实例除了几个参数外基本上都相同,有时就能够受大幅度地减少需要实例化的类的数量。
      - 如果能够将那些参数转移到类的外面,在方法调用时将他们传递进来,就可以通过共享大幅度地减少单个实例的数目。
      
    5. 自己的理解:

      1.	怎么有点MVC的感觉,用的view都是同一套,然后绑定不同的model就可以保证不同的view展示了
      2.  还有点像模板模式呢,将所有可以公用的放在内部,然后将不可以共用的作为参数传递进去。
      
    6. 何时使用

      - 如果一个应用程序使用了大量的对象,而大量的对象造成了存储开销时就应该考虑使用;
      - 对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以使用相对较少的共享对象取代很多组对象,此时可以使用享元模式
      
  3. 解释模式

    1. 定义

       解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
      
    2. 结构图

    3. 何时使用

       - 如果一种特定类型的问题发生的频率足够高,那么可鞥呢就值得将该问题的哥哥实例表述为一个简单的语言中的句子,这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
       - 相当于创建了一个小的语言,文法,然后用解释器来解释,和编译原理相关的知识比较近
      
    4. 优点 - 使用了解释器模式,就意味着可以很容易改变和扩展文法,因为该模式使用类来表示文法规则,你可以使用继承来改变或者扩展该文法。 - 也比较容易实现文法,因为定义抽象语法树各个节点的类的实现大体类似,这些类都易于直接编写。

    5. 缺点

       - 解释器模式为文法中的每一条规则都至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时使用其他技术如语法分析器,编译器生成器来处理。
      
  4. 访问者模式

    1. 定义

       访问者模式:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
      
    2. 结构图

    3. 理解

       - 将状态和行为独立出来作为一个新的类,作为参数传递给状态行为的对象;
       - 状态类中(visitor)针对固定对象种类要定义不同的行为。
       - 双分派技术: 在给对象设定visitor的时候进行了一次选择(用户实例化进行的选择),在对象的方法内部又对visitor中包含方法进行了适合自己的二次算法选择(程序内部写死的选择)
      
    4. 何时使用

       - 访问者模式适用于数据结构相对稳定的系统,指的是对象的种类是稳定的,但是对象的行为状态是不稳定的情况
       - 它把数据结构和作用于数据结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。
       - 访问者模式的目的是要把处理从数据结构分离出来
       - 当该系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式是比较合适的,因为访问者模式使得算法的操作的增加变得更加容易
      
    5. 优点

       -增加新的操作比较容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。
      
    6. 缺点

       -增加新的数据结构变得很困难
      

About

设计模式UML图

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published