工厂模式(二) —— 工厂方法模式

工厂模式(二) —— 工厂方法模式,第1张

工厂模式(二) —— 工厂方法模式 1. 絮絮叨叨
  • 针对简单工厂模式,自己曾经还说过:这根本就不算一种设计模式,是高人对长久以来的编程习惯的总结
  • 简单工厂模式中,调用者得知道自己想创建的对象的名称(传递给工厂的参数),工厂才能根据名称为其创建对应的对象
  • 要想支持新类型的对象创建,需要修改已有的工厂类代码,严重违背了开闭原则
2. 简单工厂模式的升级
  • 作为一个聪明的程序员,当老大说你的简单工厂模式代码违背了开闭原则时,你想出了一个新的实现方法
    • 每种对象的创建对应一个工厂,而不是由一个工厂去完成多种对象的创建
    • 当需要支持创建新类型的对象时,不需要修改已有的工厂类,只需要增加一个对应的工厂类即可
  • 这样的实现,没有违背开闭原则了吧?
  • 对简单工厂模式这样的升级改造,形成了一种新的设计模式 —— 工厂方法模式
  • 其UML图如下:
    • 抽象工厂:定义了创建产品的接口
    • 具体工厂:实现了抽象工厂中的抽象方法,负责具体的创建
  • 从UML图可以看出,相对简单工厂模式:
    • 工厂方法模式需要定义一个抽象工厂
    • 实现抽象工厂、创建多个具体工厂,每个工厂负责一种产品的生产
3. 代码示例
  • 需求:
    • 客户告诉你他需要支持不同格式的图片加载器,例如jpg、png、gif等
    • 使用时,他想直接获取现成的加载器实例
    • 他目前能想到上述三种图片格式,后续可能还需要支持更多图片格式
  • 考虑到系统的可扩展性,工厂方法模式就可以派上用场了:为客户提供多个工厂类,可以生成不同的图片加载器实例

创建抽象产品:

  • Reader接口

    public interface Reader {
        void read();
    }
    

创建具体产品

  • 实现Reader接口,创建各种格式的图片加载器类

    public class JpgReader implements Reader {
        @Override
        public void read() {
            System.out.print("read jpg");
        }
    }
    public class PngReader implements Reader {
        @Override
        public void read() {
            System.out.print("read png");
        }
    }
    public class GifReader implements Reader {
        @Override
        public void read() {
            System.out.print("read gif");
        }
    }
    

创建抽象工厂:

  • 抽象工厂里面有一个生成加载器实例的方法

  • 看了看好多JDK源码,通过工厂类获取对象实例时,基本都是getXXX,而非createXXX

  • 例如,ManagementFactory中的各种getXXXMXBean()方法,都是在获取对应MXBean的实例

  • 因此,这里也使用get开头命名方法

    public interface ReaderFactory {
        Reader getReader();
    }
    

创建具体工厂

  • 针对每种格式的Reader创建对应的具体工厂类
    public class JpgReaderFactory implements ReaderFactory {
        @Override
        public Reader getReader() {
            return new JpgReader();
        }
    }
    public class PngReaderFactory implements ReaderFactory {
        @Override
        public Reader getReader() {
            return new PngReader();
        }
    }
    public class GifReaderFactory implements ReaderFactory {
        @Override
        public Reader getReader() {
            return new GifReader();
        }
    }
    

客户端使用工厂类

  • 客户端使用的代码如下:
    ReaderFactory factory = new JpgReaderFactory(); // 获取工厂实例
    Reader reader = factory.getReader(); // 通过工厂创建图片加载器实例
    reader.read(); // 输出:read jpg
    
4. 工厂方法模式的优缺点

优点

  • 对调用者来说:屏蔽了对象的创建过程,只需要知道对应的工厂名称,就能获得现成的对象
  • 对开发人员来说:需要支持更多类型的对象创建时,无需修改现有的工厂类,只需要增加一个对应的工厂类即可

缺点

  • 工厂类个数容易过多:每种类型的对象的创建都需要一个对应的工厂类
  • 抽象不够:
    • 每个工厂只能创建一种类型的对象,有时需要一个工厂能创建多种类型的对象。
    • 这些对象是相关的或相互依赖的,由一个工厂来创建最合适不过了 
5. 总结
  • 工厂方法模式是对简单工厂模式的进一步抽象,可以在不修改已有代码的情况下引入新的产品(新类型的对象),满足了开闭原则
  • 会导致工厂类过多,也无法在创建一组相关或相互依赖的对象场景下使用 —— 使用抽象工厂模式解决

题外话

  • 说实话,到现在为止,自己都没有发现工厂模式有还什么高深之处
  • 自己简单搜索了一下JDK源码,好像也没有看到具体的应用
    • 最多是ManagementFactory,一个创建各种MXBean的工厂
    • 它不是单纯的简单工厂模式或者工厂方法模式,而是每种MXBean的创建都是一个单独的get方法
    • 最多可以说,是对简单工厂模式if-else语句的拆分
    • 或者是对工厂方法模式的一个改进:减少具体工厂类,只需要一个工厂;工厂中,不同的get方法实现不同对象的创建

参考链接:这是两篇不同的博客,名字相似而已

  • 工厂模式——这一篇真够了
  • 工厂模式——看这一篇就够了

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5684833.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存