16. 设计模式

16.1 设计模式的介绍   

      1) 设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验,模式[设计,思想]不是代码,而是某类问题的通用解决方案,设计模式(Design pattern)代表了最佳的实践。这些解决方案是众多软件开发人员经过相当长的一段时间试验和错误总结出来的

      2) 设计模式的本质 提高软件的维护性,通用性和扩展性,并降低软件的复杂度 

      3) <<设计模式>>是经典的,作者是 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides Design(俗称 “四人组GOF”) 

      4) 设计模式并不局限于某种语言,java,php,c++都有设计模式

16.2 设计模式类型 

      设计模式分为三种类型,共23种

      1) 创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式

      2) 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式

      3) 行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)、访问者模式

16.3 简单工厂

  16.3.1 基本介绍 

      1) 简单工厂模式是属于创建型模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式

      2) 简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)

      3) 在软件开发中,当我们会用到大量的创建某种、某类、或者某批对象时,就会使用到工厂模式  

16.4 工厂方法模式介绍 

      工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类

16.5 抽象工厂模式 

  16.5.1 基本介绍 

      1) 抽象工厂模式:定义了一个trait用于创建相关或有依赖关系的对象簇,而无需指明具体的类

      2) 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合

      3) 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)

      4) 将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类,这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展

16.6 工厂模式的小结 

      1) 工厂模式的意义:将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解藕。从而提高项目的扩展和维护性

      2) 设计模式的依赖抽象原则

        -创建对象实例时,不要直接new类,而是把这个new类的动作放在一个工厂的方法中,并返回。也有书上说,变量不要直接持有具体类的引用

        -不要让类继承具体类,而是继承抽象类或者是trait(接口)

        -不要覆盖基类中已经实现的方法

16.7 单例模式

  16.7.1 基本介绍 

      单例模式是指:保证在整个软件系统中,某个类只能存在一个对象实例

  16.7.2 单例模式的应用场景  

      比如Hibernate的SessionFactory,它充当数据存储源的代理,并负责创建Session对象。SessionFactory并不是轻量级的,一般情况下,一个项目只需要一个SessionFactory就够,这时就会使用到单例模式

  16.7.3 单例模式-懒汉式 

object boke_demo01 {

  def main(args: Array[String]): Unit = {
    val instance1 = SingleTon.getInstance
    val instance2 = SingleTon.getInstance
    if (instance1 == instance2) {
      println("相等")
    }
  }
}

//将SingleTon的构造方法私有化
class SingleTon private() {}

//懒汉式
//看底层
/*
  public SingleTon getInstance() {
    if (s() == null) {
      s_$eq(new SingleTon());
    }
    return s();
  }
 */
object SingleTon { //SingleTon$
  private var s: SingleTon = null

  def getInstance = {
    if (s == null) {
      s = new SingleTon
    }
    s
  }
}

  16.7.4 单例模式-饿汉式 

object boke_demo01 {

  def main(args: Array[String]): Unit = {
    val instance1 = SingleTon2.getInstance
    val instance2 = SingleTon2.getInstance
    if (instance1 == instance2) {
      println("相等!")
    }
  }
}


//将SingleTon的构造方法私有化
class SingleTon2 private() {}

//饿汉式
//看底层
/*
public SingleTon2 getInstance() {
    return s();
  }
 */
object SingleTon2 { //SingleTon$
  private val s: SingleTon2 = new SingleTon2

  def getInstance = {
    s
  }
}

16.8 装饰者模式 

  16.8.1 装饰者模式原理 

      1) 装饰者模式就像打包一个快递

        -主体:比如:陶瓷、衣服(Component)

        -包装:比如:报纸填充、塑料泡沫、纸板、木板(Decorator)

      2) Component 

      3) ConcreteComponent和Decorator

        ConcreteComponent:具体的主体,比如单品咖啡

      4) Decorator:装饰者,比如各调料

  16.8.2 装饰者模式定义 

      1) 装饰者模式:动态的将新功能附加到对象上,在对象功能扩展方面,它比继承更有弹性(递归),装饰者模式也体现了开闭原则(ocp)   

16.9 观察者模式 

  16.9.1 观察者模式原理 

      -观察者模式类似订牛奶业务

        1) 奶站:Subject

        2) 用户:Observer

      -Subject:登记注册、移除和通知

        1) registerObserver 注册

        2) removeObserver 移除

        3) notifyObservers() 通知所有的注册用户,根据不同需求,可以是更新数据,让用户来取,也可能是实施推送,看具体需求定

        

      -Observer:接收输入 

        

      -观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化,比如这里的奶站是Subject,是1的一方。用户Observer是多的一方

16.10 代理模式(Proxy) 

  16.10.1 代理模式的基本介绍  

      1) 代理模式:为一个对象提供一个替身,以控制对这个对象的访问

      2) 被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象(动态代理)

      3) 代理模式有不同的形式(比如 远程代理,静态代理,动态代理),都是为了控制与管理对象访问

  16.10.2 动态代理 

      -动态代理:运行时动态的创建代理类(对象),并将方法调用转发到指定类(对象)

      -动态代理调用的机制图

      

      1) Proxy和InvocationHandler组合充当代理的角色

      2) RealSubject是一个实际对象,它实现接口Subject

      3) 在使用时,我们不希望直接访问RealSubject的对象,比如:我们对这个对象的访问是有控制的

      4) 我们使用动态代理,在程序中通过动态代理创建RealSubject,并完全调用

      5) 动态代理可以根据需要,创建多种组合

      6) Proxy也会实现Subject接口的方法,因此,使用Proxy+Invocation可以完成对RealSubject的动态调用

      7) 但是通过Proxy调用RealSubject方法是否成功,是由InvocationHandler来控制的(这里其实就是保护代理)

      8) 理解:创建一个代理对象替代被调用的真实对象,使用反射实现控制

  16.10.3 几种常见的代理模式介绍-几种变体 

      1) 防火墙代理

        内网通过代理穿透防火墙,实现对公网的访问

      2) 缓存代理

        比如:当请求图片文件等资源时,先到缓存代理取,如果取到资源则ok,如果取不到资源,再到公网或者数据库取,然后缓存

      3) 静态代理

        静态代理通常用于对原有业务逻辑的扩充。比如持有第二方包的某个类,并调用了其中的某些方法。比如记录日志、打印工作等。可以创建一个代理类实现和第二方方法相同的方法,通过让代理类持有真实对象,调用代理类方法,来达到增加业务逻辑的目的

      4) Cglib

        使用cglib[Code Generation Library]实现动态代理,并不要求委托类必须实现接口,底层采用asm字节码生成框架生成代理类的字节码

      5) 同步代理

        主要使用在多线程编程中,完成多线程间同步工作

  

猜你喜欢

转载自www.cnblogs.com/zhanghuicheng/p/10890129.html