设计模式02:创建型模式

设计模式02:创建型模式

设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验

通用解决方案,软件的维护性,通用性和扩展性,并降低软件的复杂度

三种类型,共23种:

  • 创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式
  • 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式
  • 行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)

1.单例模式

对某个类只能存在一个对象实例

该类只提供一个取得其对象实例的方法(静态方法)

八种方式:

  • 饿汉式(静态常量) :
  • 饿汉式(静态代码块)
  • 懒汉式(线程不安全)
  • 懒汉式(线程安全,同步方法)
  • 懒汉式(线程安全,同步代码块)
  • 双重检查
  • 静态内部类
  • 枚举

1.1 饿汉式

类加载就会导致该单实例对象被创建

1.静态常量

  • 构造器私有化 (防止 new )
  • 类的内部创建对象
  • 向外暴露一个静态的公共方法

优点:类装载的时候就完成实例化,避免了线程同步问题

缺点:没有达到Lazy Loading;若从未使用过这个实例,则会造成内存的浪费

2.静态代码块

在静态代码块中创建单例对象

1.2 懒汉式

类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建

1.线程不安全

调用getInstance方法时才创建单例对象

  • 起到了Lazy Loading的效果,但只能在单线程下使用
  • 多线程下,可能会产生多个实例
  • 实际开发中,不要使用这种方式

2.线程安全:同步方法

getInstance加入 synchronized

效率太低,不推荐使用

3.线程安全:同步代码块

不能使用

4.双重检查

  • Double-Check概念是多线程开发中常使用到的
  • 实例化代码只用执行一次,加入 synchronized,再次访问时直接return实例化对象
  • 线程安全;延迟加载;效率较高
  • 推荐使用
  • 双重检查锁模式带来空指针异常的问题,只需要使用 volatile 关键字, volatile 关键字可以保证可见性和有序性

5.静态内部类

  • 类装载的机制来保证初始化实例时只有一个线程
  • 需要实例化时,调用getInstance方法,调用静态内部类中的实例,才会装载静态内部类
  • 避免了线程不安全,延迟加载,效率高
  • 推荐使用

6.枚举

  • 避免多线程同步,防止反序列化重新创建新的对象
  • 推荐使用

1.6 总结

  • 单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
  • 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使 用new
  • 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象频繁访问数据库或文件的对象(比如数据源、session工厂等)

2.工厂模式

用工厂来生产对象

咖啡店获取咖啡,但具体的种类与咖啡店耦合

2.1 简单工厂

简单工厂包含如下角色:

  • 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能
  • 具体产品 :实现或者继承抽象产品的子类
  • 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品

简单工厂类根据type创建Coffee对象,咖啡店与咖啡实现类解耦

如果再加新品种咖啡,仍要修改SimpleCoffeeFactory的代码,违反了开闭原则。

2.2 工厂方法模式

完全遵循开闭原则

定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。

工厂方法使一个产品类的实例化延迟到其工厂的子类。

主要角色:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应

不同工厂创建不同产品,咖啡店使用抽象工厂类创建产品

增加新的产品只要添加具体产品类和对应具体工厂类,无须修改原工厂,满足开闭原则,同时增加了系统的复杂度

2.3 抽象工厂模式

将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族

抽象工厂模式是为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构

主要角色:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,包含多个创建不同等级产品的方法
  • 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品创建
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,有多个抽象产品
  • 具体产品(ConcreteProduct):实现抽象产品定义的接口,由具体工厂创建,同具体工厂之间是多对一

甜点和咖啡有不同实现产品,而同一产品族同一实现工厂生成

保证客户端始终只使用同一个产品族中的对象

需要增加一个新的产品时,所有的工厂类都需要进行修改

2.4 模式扩展

工厂模式+配置文件:解除工厂对象和产品对象的耦合

在工厂类中加载配置文件中的全类名,并创建对象进行存储,客户端直接进行获取即可

3.原型模式

已经创建的实例作为原型,通过复制该原型对象来创建新对象

角色:

  • 抽象原型类:规定了具体原型对象必须实现 clone() 方法
  • 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象
  • 访问类:使用具体原型类中的 clone() 方法来复制新的对象

浅克隆:创建一个新对象,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址

深克隆:创建一个新对象。引用的其他对象也会被克隆

Java中的Object类中提供了 clone()方法来实现浅克隆

实现了Cloneable接口的子实现类就是具体的原型类

进行深克隆需要使用对象流:必须实现Serializable接口

ObjectOutputStream输入到文件writeObject

ObjectInputStream读取对象readObject

4.建造者模式

复杂对象的构建与表示分离

同样的构建过程可以创建不同的表示

  • 分离了部件的构造(由Builder来负责)和装配(由Director负责)
  • 构建和装配的解耦,将部件和其组装过程分开

角色:

  • 抽象建造者类(Builder):接口规定要实现复杂对象的部分的创建
  • 具体建造者类(ConcreteBuilder):实现 Builder 接口,完成部件的具体创建,提供产品的实例
  • 产品类(Product):要创建的复杂对象
  • 指挥者类(Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建

常在以下场合使用

  • 创建的对象较复杂,由多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的
  • 创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表示是独立的

5.比较

工厂方法模式:注重的是整体对象的创建方式

建造者模式:注重的是部件构建的过程

抽象工厂模式实现对产品家族的创建

建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品

posted @ 2021-05-23 17:33  FremontUltimate  阅读(68)  评论(0编辑  收藏  举报