设计模式(五)——简单工厂模式

前言

前面我们学习了相对简单的 原型模式 今天就让我们一起来学习下另外一个很简单的模式:简单工厂模式

按照惯例我们先看下工厂的概念

工厂:又称制造厂,是一所用以生产货物的大型工业楼宇。大部分工厂皆设有以大型机器或设备构成的生产线。

解决了什么问题:

我们都知道,现实中的工厂解决的是生产力低下的问题。那软件中的工厂呢?

软件中的工厂其实跟现实中的工厂很像,都是为了解决创建产品的问题。

现实中的工厂,我们扔进去材料,工厂生产成产品,我们不需要管他怎么生产的只要拿到最后的产品就行了。

软件里的工厂,我们扔进去参数,工厂生产出来对象,我们也不需要中的他是怎么实例化的,只要最后拿到相应对象就行了。

GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。

将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。今天我们就先条软柿子捏,从简单工厂模式入手。

按照惯例我们先摆出今天的内容要点:

通过这篇文章你能学到什么

(建议你可以带着问题去学习)

1、简单工厂模式的定义;
2、简单工厂模式的写法;
3、简单工厂模式的使用场景;
4、简单工厂模式的优缺点;

上面我们已经了解了简单工厂的概念和工厂在日常生活中的解释,我们再来看软件工程中简单工厂模式的定义:

简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。

我们一起来分析一下简单工厂模式的定义,可以看到,简单工厂模式的要点在于:

当你当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。简单工厂模式结构比较简单,其核心是工厂类的设计。

简单解释就是:我给你传参,你给我对象。我不需要管你是怎么创建的。

简单工程模式的类图

简单工厂模式的类图如下:

简单工厂模式类图.jpg

通过类图我们可以看到,简单工厂模式主要是有三个角色:Factory(工厂角色)、Product(抽象产品角色)、ConcreteProduct(具体产品角色),接下来我们先分别认识一下这三个角色:

Factory(工厂角色):工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象;在工厂类中提供了静态的工厂方法factoryMethod(),它的返回类型为抽象产品类型Product。

Product(抽象产品角色):它是工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂方法,因为所有创建的具体产品对象都是其子类对象。

ConcreteProduct(具体产品角色):它是简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。

看完类图和成员介绍不知道大家有没有对简单工厂模式有一个更深刻的认识?

什么还没有,好吧。那接下来我们通过一个具体的代码例子来加深一下印象。

简单的例子

我们都知道可口可乐公司生产了很多饮料,雪碧、芬达、肥仔快乐水等;那这些饮料肯定都是通过饮料工厂来生产的,那我们就用简单工厂模式来实现一下这个场景:

抽象产品:Produce —— 饮料
具体产品:ConcreteProduct —— 具体饮料
工厂:Factory —— 饮料工厂

/**
 * @description: 饮料——抽象产品
 */
interface BeveragesProduct {

    /**
     * @description: 获取饮料名称
     * @date:
     * @company:
     * @author: Meteor
     */
    fun getBeveragesName()

    /**
     * @description: 设置饮料配方
     * @date:
     * @company:
     * @author: Meteor
     */
    fun getBeveragesRecipe()
}


/**
 * @description: 可乐 —— 具体产品
 */
class Coke : BeveragesProduct {

    override fun getBeveragesName() {
        println("我是可乐:别名肥仔快乐水")
    }

    override fun getBeveragesRecipe() {
        println("配方:水,二氧化碳,可乐糖浆")
    }

}

/**
 * @description: 芬达 —— 具体产品
 */
class Fanta :BeveragesProduct{
    override fun getBeveragesName() {
        println("我是芬达")
    }

    override fun getBeveragesRecipe() {
        println("配方:水,二氧化碳,芬达糖浆")
    }
}


/**
 * @description: 雪碧 —— 具体产品
 */
class Sprite : BeveragesProduct {
    override fun getBeveragesName() {
        println("我是雪碧")
    }

    override fun getBeveragesRecipe() {
        println("配方:水,二氧化碳,雪碧糖浆")
    }
}
/**
 * @description: 饮料工厂 —— 工厂
 */
class BeveragesFactory {

    companion object {
        val TYPE_COKE = 1
        val TYPE_FANTA = 2
        val TYPE_SPRITE = 3

        fun getBeverages(type: Int): BeveragesProduct? {
            var beveragesProduct: BeveragesProduct? = null
            when (type) {
                TYPE_COKE -> {
                    beveragesProduct = Coke()
                }
                TYPE_FANTA -> {
                    beveragesProduct = Fanta()
                }
                TYPE_SPRITE -> {
                    beveragesProduct = Sprite()
                }
            }
            return beveragesProduct
        }
    }

}

/**
 * @description: 肥仔,老喝碳酸饮料
 */
class Fatty {

    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            //通过往工厂传类型,获取具体对象
            val beveragesProduct: BeveragesProduct? = BeveragesFactory.getBeverages(BeveragesFactory.TYPE_COKE)
            beveragesProduct?.getBeveragesName()
            beveragesProduct?.getBeveragesRecipe()
        }
    }
}

工作中使用的场景

简单工厂模式在工作中有很多应用的地方,具体在哪里使用,参照下面两个因素就可以了:

1、工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
2、客户端只知道传入工厂类的参数,对于如何创建对象并不关心。

优点

简单工厂模式的优点主要有以下几点:

1、 工厂类包含必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的职责,而仅仅“消费”产品,简单工厂模式实现了对象创建和使用的分离。

2、 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以在一定程度减少使用者的记忆量。

3、通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

缺点

当然简单工厂模式也有它的缺点:

1、由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响。

2、使用简单工厂模式势必会增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度。

3、系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

4、简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。

总结

其实简单工厂模式还是相对比较好理解的,通俗点说就是把我们之前各种通过 if 判断后创建的对象,封装了起来(因为工厂里面也是通过if判断的),不过把这块单独抽离了出来,做了解耦方便我们维护和管理。

简单工厂模式属于工厂模式和抽象工厂模式的基础,先学好这个对学习后面两个有帮助。

设计模式目录

设计模式(一)—— 认识设计模式
设计模式(二)—— 技术直男正确“面向对象”的六大原则
设计模式(三)—— 单例模式
设计模式(四)—— 原型模式
设计模式(五)—— 简单工厂模式

参考资料

《设计模式——可复用面向对象软件的基础》
《Head First设计模式》
《大话设计模式》
《设计模式之禅》
《Android 源码设计模式解析与实战》

刘伟

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352