设计模式之单例模式与工厂方法

设计模式

设计模式是一套被反复使用的,多数人知晓的,经过分类编目的,代码设计经验的总结。使用设计模式是为了可重用代码。

单例模式

  1. 定义:单例模式确保只有一个实例,而且自行实例化并向整个系统提供这个实例。

  2. 类型:创建类模式

  3. 组成:私有构造方法则不能通过构造方法来创建类,静态属性在类加载时就创建了一个对象,公有静态方法保证外部类可以直接调用。

    • 私有的构造方法
    • 指向自己实例的私有静态引用
    • 以自己实例为返回值的静态的公有方法
  4. 实现:

    1. 饿汉式单例:单例类被加载时候,就实例化一个对象交个自己引用

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      public class Singleton {
      private Singleton() {
      }
      private static Singleton singleton = new Singleton();
      public static Singleton getInstance() {
      return singleton;
      }
      }
    2. 懒汉式实例:调用取得方法实例时才会实例化对象

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      public class Singleton1 {
      private Singleton1(){
      }
      private static Singleton1 singleton1;
      public static synchronized Singleton1 getInstacne(){
      if (singleton1 == null)
      singleton1 = new Singleton1();
      return singleton1;
      }
      }
  5. 优点:

    • 内存中只有一个对象,节省内存空间
    • 避免频繁的创建和销毁对象,可以提高性能
    • 避免对共享资源的多重占用
    • 可以全局访问
  6. 应用场景:

    • 需要频繁实例化然后销毁的对象
    • 创建对象耗时过多或者消耗资源过多,但又经常用到的对象。
    • 有状态的工具类对象
    • 频繁访问数据库或文件的对象
  7. 注意事项:

    • 只能使用单例类提供的方法获得单例对象,不要使用反射,否则会实例化一个新对象。
    • 不要做断开单例类对象与类中静态引用的操作。
    • 多线程使用单例共享资源时,注意线程安全的问题。
  8. 相关问题:

    • 单例模式的对象长时间不用会被jvm回收吗?
      不会,Hotspot中只要对象和GC Roots之间有可达引用链,也就是单例对象和单例中的引用没有被断开就不会被回收。

    • 一个jvm中会出现多个单例吗?
      不使用反射的话,在一个jvm中不会出现多个单例。

    • 单例模式只有饿汉和懒汉两种吗?
      所有可以实现一个实例的类,都是单例模式。

    • 单例模式可以被继承吗?
      饿汉和懒汉,private方法不可以被继承。

工厂方法模式

  1. 定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。

  2. 类型:创建类模式

  3. 实现:

    工厂模式根据抽象程度的不同分为三种:

    • 简单工厂模式(静态工厂模式):创建一个工厂来创建新的对象。

      Alt text

      工厂类

      1
      2
      3
      4
      5
      6
      7
      8
      public class Factory {
      public Product createFactory(int type) {
      if (type == 1)
      return new Product1();
      else
      return new Product2();
      }
      }

      产品抽象类和具体产品

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      public abstract class Product {
      }
      public class Product1 extends Product{
      public Product1() {
      System.out.println("product1");
      }
      }
      public class Product2 extends Product{
      public Product2() {
      System.out.println("product2");
      }
      }

      消费者

      1
      2
      3
      4
      5
      6
      7
      public class Customer {
      public static void main(String[] args) {
      Factory factory = new Factory();
      Product product1 = factory.createFactory(1);
      Product product2 = factory.createFactory(2);
      }
      }
      • 组成:

        • 工厂类:用于创建商品
        • 抽象产品:具体产品继承的父类或者实现的接口
        • 具体产品:工厂类创建的对象
      • 此时当我们想要添加一种产品时,需要修改工厂类的业务员逻辑,实际中对应很多产品,对于工厂类来说负担太大,因此引入工厂方法模式,也就是讲工厂类定义成接口,增加一个商品,就增加该商品对应的工厂类的实现。

    • 工厂方法模式

      Alt text

      产品类:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      public interface IProduct {
      public void productMethod();
      }
      public class Product implements IProduct{
      @Override
      public void productMethod() {
      System.out.println("产品");
      }
      }
      public class Product1 implements IProduct{
      @Override
      public void productMethod() {
      System.out.println("产品1");
      }
      }

      工厂类

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      public interface IFactory {
      public IProduct createProduct();
      }
      public class Factory implements IFactory{
      @Override
      public IProduct createProduct() {
      return new Product();
      }
      }
      public class Factory1 implements IFactory{
      @Override
      public IProduct createProduct() {
      return new Product1();
      }
      }

      客户类

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      public class Client {
      public static void main(String[] args) {
      IFactory factory = new Factory();
      IProduct product = factory.createProduct();
      product.productMethod();
      IFactory factory1 = new Factory1();
      IProduct product1 = factory1.createProduct();
      product1.productMethod();
      }
      }

      工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式中集中在工厂方法中的压力就转到不同的工厂子类这种去了。

      • 组成:

        • 抽象工厂:具体工厂必须实现的接口或父类
        • 具体工厂:含有和具体业务逻辑有关的代码。
        • 抽象产品:具体产品继承的接口或父类。
        • 具体产品:创建产品的类。
      • 工厂方法模式对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口。这样的缺点是使得对象的数量成倍增加。

    • 抽象工厂模式

      产品类

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      public interface IProductA {
      public void productMethod();
      }
      public class ProductA implements IProductA {
      @Override
      public void productMethod() {
      System.out.println("A产品");
      }
      }
      public class ProductA1 implements IProductA {
      @Override
      public void productMethod() {
      System.out.println("A产品1");
      }
      }
      public interface IProductB {
      public void productMethod();
      }
      public class ProductB implements IProductB {
      @Override
      public void productMethod() {
      System.out.println("B产品");
      }
      }
      public class ProductB1 implements IProductB {
      @Override
      public void productMethod() {
      System.out.println("B产品1");
      }
      }

      工厂类

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      public interface AbstratFactory {
      public IProductA createProductA();
      public IProductB createProductB();
      }
      public class Factory implements AbstratFactory{
      @Override
      public IProductA createProductA() {
      return new ProductA();
      }
      @Override
      public IProductB createProductB() {
      return new ProductB();
      }
      }
      public class Factory1 implements AbstratFactory{
      @Override
      public IProductA createProductA() {
      return new ProductA1();
      }
      @Override
      public IProductB createProductB() {
      return new ProductB1();
      }
      }

      客户端

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      public class Client {
      public static void main(String[] args) {
      //生产产品
      AbstratFactory factory = new Factory();
      IProductA productA = factory.createProductA();
      productA.productMethod();
      IProductB productB = factory.createProductB();
      productB.productMethod();
      //生产产品1
      AbstratFactory factory1 = new Factory1();
      IProductA productA1 = factory1.createProductA();
      IProductB productB1 = factory1.createProductB();
      productA1.productMethod();
      productB1.productMethod();
      }
      }
      • 无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。
Donate comment here