前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式之简单工厂模式

设计模式之简单工厂模式

作者头像
Dylan Liu
发布2019-08-05 17:25:37
3350
发布2019-08-05 17:25:37
举报
文章被收录于专栏:dylanliudylanliu

撸了今年阿里、头条和美团的面试,我有一个重要发现.......>>>

简介

简单工厂模式 Simple Factory Pattern 也叫静态工厂方法模式 Static Factory Method Pattern,隶属于设计模式中的创建型模式。简单工厂通过一个静态方法来给使用方提供类创建的方式,将对象创建的控制权由使用方转换到提供方,可以将使用方和提供方具体的实现解耦,提供方就可以在用户无感知的情况下进行具体实现的替换。

角色

简单工厂模式涉及到3个角色,分别是工厂角色、抽象产品角色、具体产品角色。具体产品是抽象产品的某个实现。

这里的产品也是很抽象的一个概念。按照平时的实践,抽象产品角色可以是策略模式,具体产品角色就是某个策略;抽象产品可以是命令模式,具体产品角色就是某个命令;抽象产品角色也可以是创建型模式中的抽象工厂,具体产品角色就是某个具体的工厂类。只要涉及到继承关系,简单工厂模式就有可能的用武之地,而设计模式是继承使用的重场景,所以简单工厂模式是可以和设计模式的其他模式很好的结合起来的。

模式结构

简单工厂模式通常是以参数来决定我们创建的类的类型的,参数的使用完全取决于简单工厂模式的提供方。我们以策略模式为例,在排序场景使用简单工厂模式来做模式结构说明。

代码语言:javascript
复制
// 抽象产品角色,此处为策略模式接口
public interface Sort {
    public void sort(List<Comparable<T>> list);
}

// 具体产品角色,此处为两个排序的具体实现
public class BubbleSort implements Sort {
    public void sort(List<Comparable<T>> list) {
        //使用冒泡算法对 list 进行排序
    }
}

public class QuickSort implements Sort {
    public void sort(List<Comparable<T>> list) {
        // 使用快排算法对 list 进行排序
    }
}

// 工厂角色
// 我们知道在待排数据量很大时使用快排效果最好
// 在数据量小的时候,使用冒泡、插入排序算法效果最好
// 因此我们根据数据量 size 来决定使用哪种排序算法
public class SortFactory {
    public static int THRESHOLD = 16;
    
    public static Sort getSortInstance(int size) {
        if (size <= THRESHOLD) {
            return new BubbleSort();
        }
        
        return QuickSort();
    }
}

使用场景

使用场景决定于模式解决的问题,简单工厂模式要解决的是对象的实例化问题,因此只要有实例化的场景就有可能用到简单工厂模式,像在角色这一节中已经介绍的几个例子,但是也要注意简单工厂模式最好符合以下的条件:

  1. 由于创建过程有简单工厂负责,因此具体产品的数量不宜过多,过多的话就会导致简单工厂模式成为修改瓶颈,也不利于维护
  2. 客户端不需要了解被创建类的细节,而只通过抽象产品角色即可工作
  3. 对类的数量没有限制,在一些客户端上,有时需要限制包大小,简单工厂模式会多创建一个类出来,需要考虑。

最佳实践

  1. 简单工厂模式很多时候都是一个简单的参数比较,如下:
代码语言:javascript
复制
public class SimpleFactory {
    public static Product getInstance(int param) {
        if (param == 1) {
            return new ConcreteProduct1();
        }
        
        if (param == 2) {
            return new ConcreteProduct2();
        }
        
        return null;
    }
}

在只有简单的几个实现时,这样写还可以接受,但是当新增实现类时,我们就需要修改简单工厂方法的代码,这违背了设计原则中的开闭原则,对这种情况我们可以使用查表法。

代码语言:javascript
复制
public class SimpleFactory {
    public static Map<Integer, Product> productMap = new HashMap<>();
    
    static {
        productMap.put(1, new ConcreteProduct1());
        productMap.put(2, new ConcreteProduct2());
    }
    public static Product getInstance(int param) {
        return productMap.get(param);
    }
}

注意,这个实现和上面的实现并不完全一致,因为在每次查表时返回的都是同一个实例,这适合于 Service 等无状态的类,如果需要每次都需要返回一个新的实例,可以使用 Map<Integer, Class<Product>> 的形式,在每次调用时使用newInstance 来获取新实例。

  1. 简单工厂不仅限于简单的参数相等比较,像我在上面举的排序的例子,简单工厂是可以实现某些策略的。不要自己局限住了。
  2. 使用外部配置文件的方法来配合简单工厂。很多时候简单工厂的参数和实例的关系是直接写在代码中,或者在一个 map 中,但如果需要将工厂的实例对应关系变为可配置的,由使用方决定采用哪个类,我们就可以将配置关系放到配置文件中,简单工厂读取配置文件来加载对应关系。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 角色
  • 模式结构
  • 使用场景
  • 最佳实践
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档