设计模式 - 工厂模式

原创 2016年08月28日 17:19:13

基本概念

1.定义

  • 工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。

  • 简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式(Virtual Constructor Pattern)多态工厂模式(Polymorphic Factory Pattern)

  • 它属于类创建型模式


2.特征

  • 简单工厂模式最大的缺点是当有新产品要加入到系统中时,必须修改工厂类,需要在其中加入必要的业务逻辑,这违背了“开闭原则”。此外,在简单工厂模式中,所有的产品都由同一个工厂创建,工厂类职责较重,业务逻辑较为复杂,具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性,而工厂方法模式则可以很好地解决这一问题。

  • 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级结构:

这里写图片描述


3.角色

与简单工厂模式相比,工厂方法模式最重要的区别是引入了抽象工厂角色,抽象工厂可以是接口,也可以是抽象类或者具体类:

  • Product(抽象产品):它是定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。

  • ConcreteProduct(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。

  • Factory(抽象工厂):在抽象工厂类中,声明了工厂方法(Factory Method),用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。

  • ConcreteFactory(具体工厂):它是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实例。


模式分析

1.场景分析

假设某公司欲开发一个系统运行日志记录器(Logger),该记录器可以通过多种途径保存系统的运行日志,如通过文件记录或数据库记录,用户可以通过修改配置文件灵活地更换日志记录方式。

现在开发人员最初使用简单工厂模式对日志记录器进行了设计:

这里写图片描述

这里来看该工厂类的代码:

//日志记录器工厂  
class LoggerFactory {  

    Logger logger = null;

    public final static Logger createLogger(String args) {  
        if("db".equalsIgnoreCase(args)) {  
            logger = new DatabaseLogger();   
        }
        else if("file".equalsIgnoreCase(args)) {  
            logger = new FileLogger();   
        } 
        return logger;
    }  
}

观察代码,可以发现该设计方案具有以下缺点:

  • 条件判断语句过多:一旦记录器的类型增加,在该工厂类中就会包含很多“if…else…”代码块,导致代码相当冗长,代码越长,阅读难度、维护难度和测试难度也越大;而且大量条件语句的存在还将影响系统的性能,程序在执行过程中需要做大量的条件判断。

  • 违反了开闭原则:当需要增加新类型的记录器时,必须修改 LoggerFactory 类的源代码。


2.实例探究

下面采用工厂方法模式来解决以上的问题。

这里写图片描述

  • Looger接口充当抽象产品类;

  • Logger其子类 FileLogger、DatabaseLogger 充当具体产品类;

  • LoggerFactory 充当抽象工厂类;

  • LoggerFactory 其子类 FileLoggerFactory、DatabaseLoggerFactory 充当具体工厂类。

//日志记录器接口:抽象产品  
interface Logger {
    public void writeLog();
}

// 数据库日志记录器:具体产品
class DatabaseLogger implements Logger {
    public void writeLog() {
        System.out.println("数据库日志记录。");
    }
}

// 文件日志记录器:具体产品
class FileLogger implements Logger {
    public void writeLog() {
        System.out.println("文件日志记录。");
    }
}

// 日志记录器工厂接口:抽象工厂
interface LoggerFactory {
    public Logger createLogger();
    public void writeLog();
}

// 数据库日志记录器工厂类:具体工厂
class DatabaseLoggerFactory implements LoggerFactory {
    public Logger createLogger() {
        return new DatabaseLogger();
    }

    public void writeLog() {
        Logger logger = this.createLogger();
        logger.writeLog();
    }
}

// 文件日志记录器工厂类:具体工厂
class FileLoggerFactory implements LoggerFactory {
    public Logger createLogger() {
        return new FileLogger();
    }

    public void writeLog() {
        Logger logger = this.createLogger();
        logger.writeLog();
    }
}

// 客户端测试
public class Test {
    public static void main(String [ ] args) {
        LoggerFactory factory = new FileLoggerFactory();
        factory.writeLog();
    }
}

总结

工厂方法模式的优缺点:

  • 优点是增加新的产品类时无须修改现有系统;封装了产品对象的创建细节,系统具有良好的灵活性和可扩展性;

  • 缺点在于增加新产品的同时需要增加新的工厂,导致系统类的个数成对增加,在一定程度上增加了系统的复杂性。

工厂方法模式适用情况:

  • 一个类不知道它所需要的对象的类;

  • 一个类通过其子类来指定创建哪个对象;

  • 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。


参考

版权声明:本文为博主原创文章,未经博主允许不得转载。

设计模式之简单工厂模式

  • 2014年08月17日 14:51
  • 33KB
  • 下载

JAVA设计模式之抽象工厂模式

  • 2014年10月14日 10:46
  • 10KB
  • 下载

C++设计模式[一]工厂模式

一直想好好学习一下设计模式,终于发现了一个通熟易懂的C++设计模式解释,最近有点懒,然后就转过来了。 =================================================...

05_C_设计模式-抽象工厂模式

  • 2014年10月08日 16:24
  • 3.28MB
  • 下载

设计模式(一)----工厂模式

基本的业务逻辑的编写并不是难事,作为一个合格的程序员能够编写出易扩展,可维护,高内聚,低耦合的代码才是真正的能力。所以从今天开始会陆陆续续的研究一下设计模式。设计模式并不是针对编程语言,而是考察的编程...

设计模式之简单工厂模式

  • 2014年04月23日 11:23
  • 29KB
  • 下载

设计模式_工厂模式

  • 2014年09月17日 13:28
  • 7KB
  • 下载

设计模式(一)工厂模式Factory(创建型)

设计模式一 工厂模式Factory          在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接...
  • hguisu
  • hguisu
  • 2012年04月25日 21:29
  • 102776
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式 - 工厂模式
举报原因:
原因补充:

(最多只允许输入30个字)