Fork me on GitHub

大战设计模式(第二季)【1】———— 从源码看工厂模式

前言

工厂模式其实在许多地方都有体现,是常见的一种设计模式。用一句话总结就是,当我们需要创建一些对象的时候,而创建的对象比较复杂或者同类型比较多,就可以使用它。

在我们看源码的时候,有的时候看见XXXFactory那么它就使用了工厂模式。

工厂模式的基础知识点:
简单工厂:https://www.cnblogs.com/linkstar/p/7657865.html
工厂方法:https://www.cnblogs.com/linkstar/p/7667799.html
抽象工厂:https://www.cnblogs.com/linkstar/p/7672733.html

 

全部设计模式:https://www.cnblogs.com/linkstar/category/1087887.html 

 

Calendar来看简单工厂

首先我们常见的jdk中有一个叫做Calendar的类,它是专门用来处理时间的,它是一个抽象类,我们只能使用getInstance方法获取这个类的实例。

然后然后其中会通过createCalendar方法去创建这个对象。因为各个国家的日历可能都有所不同,所以需要根据地区来返回对应的实现,比如日本的话就会返回JapaneseImperialCalendar对象。

这里其实就是简单工厂的一个体现,根据具体传入的参数不同,返回的不同实现的产品。

 

从Collection看工厂方法

在jdk中Collection接口中有一个iterator方法,这个方法是返回一个迭代器对象,这个对象是用来遍历集合的,我们在一开始学习java的时候就经常使用迭代器来遍历集合。

这其实就是一个工厂方法,而这个方法的具体实现的各个工厂就有很多了,比如ArrayList,HashSet等,他们都是工厂,而抽象的产品是Iterator接口。

而每个工厂具体产出的实际产品是如下这样产出的,

这个是ArrayList的,可以看到返回的产品就是一个私有的内部类。


这个是HashSet的,可以看到的返回的产品就不一样了,是map的keySet。

这样设计的原因是:我们在使用迭代器进行遍历的时候方法都需要是一样的,next还有hasNext,用于获取下一个元素还有判断是否有下一个元素,但是针对于不同的集合因为存储的方式不一样所以这两个方法的实现肯定是不一样的,所以设计成了这样。

 

从MyBatis看抽象工厂

其实在Collection接口中我们已经可以看出抽象工厂的影子了,为了加深理解,我们再看看我们常见的ORM框架MyBatis中是怎么样的。其实我们很容易找到它,因为MyBatis使用Factory来进行命名。

PS:如果你对MyBatis框架还并不熟悉,建议熟练使用之后再进行学习。

首先我们可以看到有SqlSessionFactory这样一个接口,里面有openSession方法

然后我们可以看到它的实现一共有两个类

我们用工厂模式的方式去描述的话,SqlSessionFactory接口就是我们的抽象工厂,这里面有很多抽象出来的方法,也就是接口中包含的方法,有两个实际的工厂需要去实现这样的方法,同时生产出不同的产品。

然后我们再从产品的角度来说,工厂产出的产品这里指的是SqlSession这个对象

这个对象本身也是一个接口,也就是说它也是一个抽象的产品

从图中我们就可以看到,具体的产品也有两种,这两种正好对应了上说到的两个工厂。

如果我们针对defalut工厂来看的话,大致的结构应该是这样的:

而SqlSessionManager也是类似

产出的产品SqlSession是用于最终执行查询修改等操作的,可见SqlSession在整个框架是非常重要的一环,而SqlSession的创建和维护管理就很重要了,而且SqlSession执行肯定需要配置文件中的一些信息,不是随便new一个就完事了,所以在这里使用工厂模式创建的意义也就出现了。

 

总结

工厂模式在实际中的使用还是挺常见的,在一些其他框架也有存在,比如常见的spring中。我们可以总结出,在创建一些对象的时候,如果创建的过程在重复,创建的过程比较复杂,创建的产品同类型多,那么我们就可以考虑使用对应的工厂模式去解决。
同时在之前在基础里面说明了,产品的分类不要过多,否则如果一种产品一个工厂那么那么很容易导致类的爆炸增长。

 

posted @ 2019-02-17 20:23  LinkinStar  阅读(846)  评论(0编辑  收藏  举报