在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。Java 设计模式之工厂模式

简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之所以叫做工厂模式,是用工厂生产产品来形象的比喻代码中生产对象的过程。总体来说,工厂模式分为以下几种:

  • 简单工厂模式(Simple Factory Pattern)
  • 工厂方法模式(Factory Method Pattern)
  • 抽象工厂模式(Abstract Factory Pattern)

简单工厂模式(Simple Factory Pattern)

我们模拟一种场景,有一家汽车厂(AutoFactory)要生产汽车,现在主要生产小轿车(Car)和大巴车(Bus),那用代码模拟如下:

首先“设计”一个汽车原型(定义汽车接口),这个接口体现了所有汽车的共性:


public interface Auto {
//所有汽车都可以被驾驶
public void drive();
}

接下来我们“设计”两种汽车:小轿车和大巴车:


//小轿车
public class Car implements Auto{
@Override
public void drive(){
System.out.println(“小轿车启动了”);
}
}

//大巴车
public class Bus implements Auto{
@Override
public void drive(){
System.out.println(“大巴车启动了”);
}
}

开始“建厂”了,我们实现一个简单工厂类:


public class AutoFactory{
//生产汽车
public Auto produce(String name){
if("car".equals(name)){
return new Car();
} else if("bus".equals(name)){
return new Bus();
}
}
}

一切就绪,我们开始生产汽车了,先生产一辆小轿车:


AutoFactory factory = new AutoFactory();
Auto car = factory.produce("car");
car.drive();

简单工厂模式实现了生成产品类的代码跟具体的产品实现分离,在工厂类中你可以添加所需的生成产品的逻辑代码,但是问题来了,这不符合“开放-封闭”原则的,也就是说对扩展开放,对修改关闭,如果你要加一个新的汽车类型还需要修改produce方法,为解决这个问题,从而引入了工厂方法模式(Factory Method Pattern)。

工厂方法模式(Factory Method Pattern)

工厂为了扩大市场,现在要开始生产卡车(Truck)了,于是我们设计一辆卡车:


//卡车
public class Truck implements Auto{
@Override
public void drive(){
System.out.println(“卡车启动了”);
}
}

如果按照简单工厂的逻辑,需要修改produce方法(也就是我们要改造已有工厂),这样会影响已有生产,怎么办呢?解决办法是再新建新的工厂:

首先我们“设计”一个工厂原型(工厂接口):


public interface IAutoFactory{
//生产汽车
public Auto produce(String name);
}

然后将原来的工厂简单改造符合设计好的工厂原型(实现接口即可,所有逻辑不变):


public class AutoFactory implements IAutoFactory{
//生产汽车
@Override
public Auto produce(String name){
if("car".equals(name)){
return new Car();
} else if("bus".equals(name)){
return new Bus();
}
}
}

好的,接下来为了生产卡车,我们要为卡车单独建厂:


public class TruckAutoFactory implements IAutoFactory{
//生产卡车
@Override
public Auto produce(String name){
return new Truck();
}
}

开始生产卡车:


IAutoFactory factory = new TruckAutoFactory();
Auto car = factory.produce(null);
car.drive();

这里的抽象工厂中,我们为了减少改造成本,在简单工厂基础上做最小修改,理论上produce参数可以没有,然后为小轿车、大巴车和卡车分别建立工厂,分别生产。这样如果有了新的类型的车,可以不改动之前的代码,新建一个“工厂”即可,做到“开放封闭原则”。

虽然看似类变多了,逻辑复杂了,但是这种改造带来的好处也是显而易见的:不变动老的代码,通过新建工厂类完成新功能的添加,老功能不变,最大限度的避免动了老代码的逻辑导致引入新的bug。

工厂方法的结构图如下:

抽象工厂模式(Abstract Factory Pattern)

我们继续针对汽车工厂说明,由于接下来工厂需要继续扩大规模,开始涉足汽车配件,上层决定涉足汽车大灯业务,针对已有车型生产前大灯。但是如果按照工厂方法模式,需要再继续新建一批工厂,针对每种汽车再建N个工厂,考虑到成本和简单性,针对对已有汽车工厂改造。

首先“设计”大灯原型:


//大灯
public interface Light {
//开灯
public void turnOn();
}

再“设计”小轿车、大巴车和卡车大灯:


//小轿车大灯
public class CarLight implements Light{
@Override
public void tunOn(){
System.out.println(“小轿车大灯亮了”);
}
}

//大巴车大灯
public class BusLight implements Light{
@Override
public void tunOn(){
System.out.println(“大巴车大灯亮了”);
}
}

//卡车大灯
public class TruckLight implements Light{
@Override
public void tunOn(){
System.out.println(“卡车大灯亮了”);
}
}

接下来我们重新“设计”原有的汽车工厂(修改工厂接口或者抽象工厂类)


public interface IAutoFactory{
//生产汽车
public Auto produce();
//生产大灯
public Light produceLight();
}

好的,改造工厂,首先改造小轿车工厂:


public class CarAutoFactory implements IAutoFactory{
//生产汽车
@Override
public Auto produce(){
return new Car();
} //生产车灯
@Override
public Light produceLight(){
return new CarLight();
}
}

改造大巴车工厂:


public class BusAutoFactory implements IAutoFactory{
//生产汽车
@Override
public Auto produce(){
return new Bus();
} //生产车灯
@Override
public Light produceLight(){
return new BusLight();
}
}

改造卡车工厂:


public class TruckAutoFactory implements IAutoFactory{
//生产汽车
@Override
public Auto produce(){
return new Truck();
} //生产车灯
@Override
public Light produceLight(){
return new TruckLight();
}
}

开始生产:


//生产小轿车和小轿车大灯
IAutoFactory factory = new CarAutoFactory();
Auto car = factory.produce();
car.drive();
Light light = factory.produceLight();
light.turnOn();

//生产大巴车和小大巴车大灯
IAutoFactory factory = new BusAutoFactory();
Auto bus = factory.produce();
bus.drive();
Light light = factory.produceLight();
light.turnOn();

//生产卡车和卡大灯
IAutoFactory factory = new TruckAutoFactory();
Auto truck = factory.produce();
truck.drive();
Light light = factory.produceLight();
light.turnOn();

抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。

抽象工厂模式示意图如下:

参考资料

工厂模式在Hutool中的应用

Hutool中,Hutool-db模块为了简化和抽象连接池的创建,使用了工厂方法模式,首先定义了DSFactory


//数据源工厂
public abstract class DSFactory {
//获取数据源
public abstract DataSource getDataSource(String group);
}

然后分别创建了:HikariDSFactoryDruidDSFactoryTomcatDSFactoryDbcpDSFactoryC3p0DSFactory几种常见连接池的工厂实现,这样用户可以很容易的使用对应的连接池工厂创建需要的连接池数据源(DataSource)。

同样,用户也可以自己继承DSFactory实现抽象方法getDataSource来自定义数据源。

在此基础上,对于数据源工厂的创建,又使用了简单工厂模式,代码如下:


private static DSFactory doCreate(Setting setting) {
try {
return new HikariDSFactory(setting);
} catch (NoClassDefFoundError e) {
//ignore
}
try {
return new DruidDSFactory(setting);
} catch (NoClassDefFoundError e) {
//ignore
}
try {
return new TomcatDSFactory(setting);
} catch (NoClassDefFoundError e) {
//ignore
}
try {
return new DbcpDSFactory(setting);
} catch (NoClassDefFoundError e) {
//ignore
}
try {
return new C3p0DSFactory(setting);
} catch (NoClassDefFoundError e) {
//ignore
}
// 默认使用Hutool实现的简易连接池
return new PooledDSFactory(setting);
}

通过try的方式,按照优先级尝试创建对应连接池的工厂类,如果用户没有引入对应连接池库,就会报NoClassDefFoundError异常,从而尝试创建下一个连接池工厂,依次类推,直到发现用户未引入任何连接池库,则使用Hutool默认的简单连接池PooledDSFactory。通过这种方式,简化了用户对连接池的选择配置。

原文链接:https://my.oschina.net/looly/blog/1860776

Java设计模式学习之工厂模式的更多相关文章

  1. Java设计模式学习三-----工厂模式

    工厂模式 工厂模式(Factory Pattern)是Java中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,创建对象时不会对客户端暴露创建逻 ...

  2. Java设计模式之【工厂模式】(简单工厂模式,工厂方法模式,抽象工厂模式)

    Java设计模式之[工厂模式](简单工厂模式,工厂方法模式,抽象工厂模式) 工厂模式出现的原因 在java中,创建一个对象最简单的方法就是使用new关键字.但在一些复杂的业务逻辑中,创建一个对象不只需 ...

  3. Java 设计模式之抽象工厂模式(三)

    原文地址:Java 设计模式之抽象工厂模式(三) 博客地址:http://www.extlight.com 一.前言 上篇文章 <Java 设计模式之工厂模式(二)>,介绍了简单工厂模式和 ...

  4. Java设计模式之二 ----- 工厂模式

    在上一篇中我们学习了单例模式,介绍了单例模式创建的几种方法以及最优的方法.本篇则介绍设计模式中的工厂模式,主要分为简单工厂模式.工厂方法和抽象工厂模式. 简单工厂模式 简单工厂模式是属于创建型模式,又 ...

  5. Java设计模式之二工厂模式

    在上一篇中我们学习了单例模式,介绍了单例模式创建的几种方法以及最优的方法.本篇则介绍设计模式中的工厂模式,主要分为简单工厂模式.工厂方法和抽象工厂模式. 简单工厂模式 简单工厂模式是属于创建型模式,又 ...

  6. Java设计模式系列-抽象工厂模式

    原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755412.html 一.概述 抽象工厂模式是对工厂方法模式的再升级,但是二者面对的场景稍显差别. ...

  7. Java设计模式学习记录-模板方法模式

    前言 模板方法模式,定义一个操作中算法的骨架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤. 模板方法模式 概念介绍 模板方法模式,其实是很好理解的,具体 ...

  8. Java设计模式学习记录-状态模式

    前言 状态模式是一种行为模式,用于解决系统中复杂的对象状态转换以及各个状态下的封装等问题.状态模式是将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态可以灵活多变.这样在客户端使 ...

  9. Java设计模式学习记录-备忘录模式

    前言 这次要介绍的是备忘录模式,也是行为模式的一种 .现在人们的智能手机上都会有备忘录这样一个功能,大家也都会用,就是为了记住某件事情,防止以后自己忘记了.那么备忘录模式又是什么样子的呢?是不是和手机 ...

随机推荐

  1. (转)java volatile关键字

    转自:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 参考:http://blog.csdn.net/imzoer/ar ...

  2. 金典 SQL笔记(9)

    page301-354其它解决方式 ---开窗函数 --測试数据及表 USE [NB] GO /****** 对象: Table [dbo].[T_Person2] 脚本日期: 08/14/2015 ...

  3. UIImagePickerController在UIPopoverController中 旋屏问题

    1弧度=180/π度1度=π/180弧度今天遇到了 一个问题.UIImagePickerController在UIPopoverController中 旋屏问题. 在查找了许多资料后方知,此乃iOS系 ...

  4. 编写高质量代码--改善python程序的建议(三)

    原文发表在我的博客主页,转载请注明出处! 建议十三:警惕eval()的安全漏洞 相信经常处理文本数据的同学对eval()一定是欲罢不能,他的使用非常简单: eval("1+1==2" ...

  5. SDN开发过程中遇到的一些问题总结

    我用的是ryu控制器,用Mininet作为网络系统平台. 当启动控制器的时候如果提示:unsupported version 0x1. if possible, set the switch to u ...

  6. 3969 [Mz]平方和【斐波那契平方和】

    3969 [Mz]平方和  时间限制: 1 s  空间限制: 64000 KB  题目等级 : 大师 Master 题解  查看运行结果     题目描述 Description 斐波那契数列:f[0 ...

  7. mvc中使用uploadify批量上传的应用

    网上找了很多资料都没有发现一个好用.可以用的uploadify批量上传的应用,这里通过官方和自己的一些项目需要整理了一个出来. 希望能帮助到需要的人. 效果图:

  8. css生成三角形

     转载:http://www.cnblogs.com/lhb25/p/css-and-css3-triangle.html Triangle Up    1 2 3 4 5 6 7 #triangle ...

  9. 170110、Spring 事物机制总结

    spring两种事物处理机制,一是声明式事物,二是编程式事物 声明式事物 1)Spring的声明式事务管理在底层是建立在AOP的基础之上的.其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加 ...

  10. Jmeter--正则表达式提取值

    博客首页:http://www.cnblogs.com/fqfanqi/ 设置界面如下: Apply to:应用范围的选择: Field to check:检查的领域,即需要提取内容的地方. 下面是各 ...