设计模式之静态工厂方法

设计模式

静态工厂方法

介绍

  • 什么是静态工厂方法

    • 通过类内部的静态方法创建对象而非new

      public static void main(String[] args) {
          Calendar date = Calendar.getInstance();
          
          Integer a = Integer.valueOf(4);
      }
      // 可以看到通过Calendar的静态方法 getInstance() 就获得了一个 Calendar 对象
      
  • 透过现象看本质

    • 查看源码

      // 以较为简单的Integer为例
      public static Integer valueOf(int i) {
          if (i >= IntegerCache.low && i <= IntegerCache.high)
              return IntegerCache.cache[i + (-IntegerCache.low)];
          return new Integer(i);
      }
      public Integer(int value) {
          this.value = value;
      }
      
      • 可以看到调用了valueOf方法实际上还是使用了构造方法来进行实现

优势

  • 我们看到实际上我们使用静态工厂方法可能最后也是调用了构造方法,那么这种设计模式
    1. 对于某一个类,拥有多个参数的构造方法可能会导致调用的时候难以区分,使用静态工厂方法做一次转发可以让每一个构造方法拥有自己的名字

    2. 对于外部调用,有时候只是需要一个对象,并不需要直到这个对象是不是一个全新的实例,又或者是我们想对外提供一个单例时,如果使用工厂方法,就可以在内部预先进行判断,防止创建不必要的对象,减少内存开销

    3. 如果我们直接调用构造方法,那么必然返回的是该类的构造方法的,但是实际上我们可以在静态工厂方法里返回该类子类的对象,达到多态的效果

    4. 可以有多个参数相同但名称不同的静态工厂方法

      class Goods {
          int weight;
          int price;
          // 假如此时有两种商品
          // 一种需要论斤卖,那么它的重量必然是后面称出来的,所以只需要单价就好了
          // 那么创建这种商品的构造方法
          public Goods(int price) {
              this.price = price;
          }
      
          // 另一种商品不需要单价, 按照10块钱一斤称的, 那么就需要使用所有商品重量相加
          // 那么创建这种商品的构造方法
          // public Goods(int weight) {
          //     this.weight = weight;
          // }
          // 构造方法只能区分不同类型不同数量,对于两个都是int参数就不能区分,所以需要别的办法解决
      }
      
      class Goods {
          int weight;
          int price;
      
          public Goods(int weight, int price) {
              this.weight = weight;
              this.price = price;
          }
      
          // 一种商品只需要重量
          public Goods goodsWithWeight(int weight){
              return new Goods(weight, 0);
          }
      
          // 一种商品只需要单价
          public Goods goodsWithPrice(int price){
              return new Goods(0, price);
          }
      }
      
    5. 静态工厂方法可以减少内部代码对外暴露的可能性

      class PersonDemo {
          // 有时我们利用参数范围进行取值,但是如果直接在构造方法里面进行if判断
          // 可能会让代码看起来非常乱,而且可能会传入一些不正确的值导致报错
          // 利用静态工厂方法进行提前的筛选判定
          String gender;
          public PersonDemo(String gender) {
              this.gender = gender;
          }
      
          public PersonDemo setAge(int age){
              if (age >=0 && age < 18){
                  return new PersonDemo("未成年");
              } else if (age >= 18 && age < 120){
                  return new PersonDemo("成年人");
              } else {
                  throw new RuntimeException("年龄不正确");
              }
          }
      }
      

总结

  • 我个人觉得静态工厂方法的意义在于能够增加类的扩展性和限制类的引用方向,在最大程度上能够指导类的调用者的行为,减少对方犯错误的机会
上一篇:【手撕算法】FT显著性检测算法


下一篇:MYSQL商城简单场景处理并发,防止库存超卖