简单工厂模式——创建和使用分离


Demo 地址: https://github.com/ooblee/HelloDesignPattern

1. 定义

简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。

工厂模式的作用,将实例的创建和使用进行分离,将实例化的配置和创建的过程封装在工厂类中。

简单工厂模式是工厂三兄弟之一,但并不属于 GOF 的 23 种设计模式。

使用的时候,无需关心实例化细节,只要传递自己想要的产品类型,创建过程委托给工厂来实现。

2. 设计

主要元素:

  • 抽象产品。声明产品的属性和行为。
  • 具体产品。抽象产品的实现。
  • 具体工厂。负责产品的创建。

类图如下:

简单工厂模式-类图

2.1. 普通简单工厂

一个工厂类,一个工厂方法,对传入的类型进行枚举,实例化产品。

public class NormalSimpleFactory {

    public static final String TYPE_CHINESE = "Chinese";
    public static final String TYPE_ENGLISH = "English";
    public static final String TYPE_GERMAN = "German";

    public IProduct getProduct(String type) {
        if (TYPE_CHINESE.equals(type)) {
            return new ChineseProduct();
        } else if (TYPE_ENGLISH.equals(type)) {
            return new EnglishProduct();
        } else if (TYPE_GERMAN.equals(type)) {
            return new GermanProduct();
        } else {
            return null;
        }
    }
}

虽然还是有 if else 对类型进行判断,但对于之前零散于各处的创建代码来说已经得到了很大的优化。

2.2. 多方法简单工厂

一个工厂类,多个工厂方法,无需枚举,每种方法返回对应的实例。

public class MultiMethodFactory {

    public IProduct getChineseProduct() {
        return new ChineseProduct();
    }

    public IProduct getEnglishProduct() {
        return new EnglishProduct();
    }

    public IProduct getGermanProduct() {
        return new GermanProduct();
    }
}

可以不用去维护类型类表与类型和实例的关联管理。

2.3. 静态工厂方法(使用较多)

无需实例化工厂,调用方法直接为静态,所以也被称为 静态工厂方法

public class StaticMethodSimpleFactory {

    public static IProduct getChineseProduct() {
        return new ChineseProduct();
    }

    public static IProduct getEnglishProduct() {
        return new EnglishProduct();
    }

    public static IProduct getGermanProduct() {
        return new GermanProduct();
    }
}

3.应用

工厂模式用来就创建与使用解耦。工厂三兄弟有不同适用范围。

一般来说,简单会在几个情况下使用:

  • 需要生产的产品比较简单,数量较少(因为简单工厂把所有产品创建集中起来,多了就复杂了)。
  • 使用者无需记住创建细节,只要告诉工厂需要的类型。

3.1. JDK:MessageDigest

进行消息摘要的工具

MD2

MessageDigest md=MessageDigest.getInstance("MD2");

MD5

MessageDigest md=MessageDigest.getInstance("MD5");

SHA

MessageDigest md = MessageDigest.getInstance("SHA");

3.2. JDK:Executors

静态工厂方法提供默认的线程池。

阿里开发手册已经不推荐使用,希望我们自己创建线程池,并约束好最大任务数或最大线程数。

这里仅仅作为一个举例。

缓存线程池:

ExecutorService cacheThreadPool = Executors.newCachedThreadPool();

固定线程数线程池:

ExecutorService fixCacheThreadPool = Executors.newFixedThreadPool(10);

单线程线程池:

ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

定时执行任务线程池:

ScheduledExecutorService scheduleThreadPool = Executors.newScheduledThreadPool(4);

4. 特点

4.1. 优点

  • 易于阅读:因为类型不一样,需要 if else 分支判断,过多的 if else 代码块会造成维护困难,集中在工厂有利于代码复用和可读性。
  • 易于修改:调用者可以遵循依赖倒置原则,面向抽象编程。创建过程交给工厂实现,如果更换产品只需要调整工厂。
  • 易于复用:如果对象创建需要大量复杂的配置和初始化操作,内聚到工厂进行复用。

4.2. 缺点

  • 要修改工厂。如果要新增产品,还是要修改工厂,不符合开闭原则

    优化思路

    如果产品相当复杂的话,可以考虑改用工厂方法或抽象工厂

4.3. 注意事项

  • 生成的产品要足够简单,然后业务逻辑不能太复杂。如果创建过程过于复杂的话,可以考虑用其他模式进行配合。
发布了61 篇原创文章 · 获赞 43 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/firefile/article/details/90311696