【第22期】观点:IT 行业加班,到底有没有价值?

设计模式 - 工厂模式

原创 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();
    }
}

总结

工厂方法模式的优缺点:

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

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

工厂方法模式适用情况:

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

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

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


参考

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

相关文章推荐

Log4j 介绍

概述Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式。 输出优先级:指定了这条日志信息的重要程度。 输出目的地:指定了日志将打印到控制台还是文件中。 输出格式...

Java IO - CharArrayReader&CharArrayWriter

基本概念 CharArrayReader:此类实现一个可用作字符输入流的字符缓冲区。 CharArrayWriter:此类实现一个可用作 Writer 的字符缓冲区。缓冲区会随向流中写入数据而自动增...

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

正则表达式

正则表达式由原子,有特殊功能的字符以及修正符组成,描述了一种字符串匹配的模式,通过这个模式在特定函数中对字符串进行匹配,查找,替换以及分割等操作。正则检测工具:http://regexpal.isba...

Java 设计模式 - 建造者模式

基本概念建造者模式的作用: 将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 建造者模式的角色: Product,即产品,表示被建造的对象。该对象一定是个复杂对象,由各个部...

Java 设计模式 - 代理模式

基本概念代理模式的作用: 代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介 代理模式的角色: Subject,抽象角色,通过接口或抽象类声明真实角色实现的业务方法。...

01.JUC 锁 - 概述

基本概念J.U.C 包是 java.util.concurrent 包的简写。这个包在JDK5引入,大大增强了Java的并发特性。JDK7还引入ForkJoin框架。在 JUC 中,并发离不开锁,因为...

SpringMVC 注解

@Controller在 springmvc 2.5 之前通过继承 Controller 接口实现控制器//接口定义 public interface Controller { ModelAnd...

07.Spring Bean 加载 - BeanDefinitionReader

基本概念BeanDefinitionReader ,该接口的作用就是加载 Bean。在 Spring 中,Bean 一般来说都在配置文件中定义。而在配置的路径由在 web.xml 中定义。所以加载 B...

04.Spring Ioc 容器 - 刷新

基本概念Spring Ioc 容器被创建之后,接下来就是它的初始化过程了。该过程在 ConfigurableApplicationContext 的 refresh 方法中定义。该接口的继承关系如下:...

08.Spring Bean 解析 - BeanDefinitionDocumentReader

基本概念BeanDefinitionDocumentReader ,该类的作用有两个,完成 BeanDefinition 的解析和注册 。 解析:其实是解析 Ddocument 的内容并将其添加到 B...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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