设计模式概述

设计原则:

  • 开闭原则OCP(Open Close Principle)

    扩展开放,修改关闭

  • 氏代换原则LSP(Liskov Substitution Principle)

    任何基类可以出现的地方,子类一定可以出现。子类当父类用个性被抹杀,直接使用子类,违背了面向接口编程,缺乏替代关系

  • 依赖倒转原则DIP(Dependence Inversion Principle)

    针对接口编程,依赖于抽象而不依赖于具体。避免个性子类

  • 接口隔离原则(Interface Segregation Principle)

    使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思。完全满足接口隔离原则,在部分使用场景下接口会增多。用户会实现多个自己关心的接口,增加用户使用陈本.

  • 迪米特法则(最少知道原则)(Demeter Principle)

    一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

  • 合成复用原则(Composite Reuse Principle)

    原则是尽量使用合成/聚合的方式,而不是使用继承。

设计模式:

  • 创建型(5)

    简单工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式。

    • 简单工厂模式:
      工厂中的具体方法隐藏了所有实现细节

      • 普通工厂(传参数,没一个参数决定一个产品)
      • 多工厂方法(不用传参数,每个方法决定一个产品)
      • 静态工厂方法(工厂的实现方式,不用new工厂,通过工厂的静态方法创建对象)
    • 抽象工厂模式(Abstract Factory)

    工厂方法模式不满足开闭原则,抽象工厂通过增加工厂类的方法来支持开闭原则,产品族和工厂族是对等的

    之所以叫抽象工厂模式是相对于工厂方法模式的。因为该模式中对工厂进行了抽象,抽象出了和产品层级对等的工厂层级.而简单工厂模式中工厂是具体的,包含了所有实现细节

    • 单例模式

    单例对象能保证在一个JVM中,该对象只有一个实例存在

    • 饿汉式
    • 懒汉式
    • 建造者模式

    工厂模式关注的是创建单个产品,而建造者模式则关注创建符合对象,多个部分。

    • 原型模式(Prototype)
    • 浅复制(浅克隆shallow clone ):将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。

    • 深复制(深克隆deep clone):将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。深度clone对象必须实现序列化接口 Serializable

      实现方式: 通过把对象序列化到内存,然后再读出来

      public Object deepClone() throws IOException, ClassNotFoundException {  
      
          /* 写入当前对象的二进制流 */  
          ByteArrayOutputStream bos = new ByteArrayOutputStream();  
          ObjectOutputStream oos = new ObjectOutputStream(bos);  
          oos.writeObject(this);  
      
          /* 读出二进制流产生的新对象 */  
          ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  
          ObjectInputStream ois = new ObjectInputStream(bis);  
          return ois.readObject();  
      }  
      

  • 结构型模式(7)

    适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式

    • 适配器模式

    在开闭原则的基础上,不修改原有代码的同时,提供满足接口需求的功能组件。

    • 类适配器

      当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。

      编写适满足调用需求的适配器类,适配器类继承原类获得原类功能,适配器把被适配的接口转换成目标接口。

    • 对象适配器

      当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行。

      编写满足调用需求的适配器类,组合原有对象, 把原类的功能转换成目标接口接口: 目标类只想实现一个接口中的部分抽象方法。构造抽象类,抽象类实现接口中的所有方法,之所以使用抽象类,这样可以阻止对该适配器的实例化,目标类就可以继承该适配器,重写想重写的方法。

    • 接口适配器

      当不希望实现一个接口中所有的抽象方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。

      个人理解:接口适配器不符合接口隔离原则,出现某个类只想实现接口中的部分接口的情况,是接口提供的太大,接口没有很好的隔离造成的。

    • 装饰器模式

    动态的为某个类增加功能,还能撤销. 装饰类和被装饰类实现相同的接口

    装饰器模式的应用场景:

    1. 需要扩展一个类的功能。
    2. 动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删)。

      缺点:产生过多相似的对象,不易排错!

    • 代理模式

    从结构上和装饰模式差不多,但是关注点不一样。装饰模式关注的是增加新功能,而代理模式关注的是对原有接口功能的控制(结果的控制)。具体的实现方法和 装饰模式差不多。

    代理模式的应用场景:

    如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:

    1. 修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。
    2. 就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

    使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

    • 外观模式(Facade),也称门面模式

    门面模式遵循 迪米特法则,用门面对象隐藏细小对象和复杂对象。简化客户端调用,减少客户端依赖。

    • 桥接模式
    • 组合模式

    • 享元模式

  • 行为行(11)

    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

    • 策略模式
    • 模板方法模式

    • 观察者模式

    • 迭代子模式

    • 责任链模式

    • 命令模式

    命令的发送者和实现者解耦

    • 备忘录模式

    把原始对象的状态记录并存储起来,原始对象状态改变以后,可以在某个时候恢复。

    • 状态模式

    当对象的状态改变时,同时改变其行为

    • 访问者模式

    • 中介者模式

    • 解释器模式