创建型模式之工厂模式

in HandbookDesign Patterns with 40 comments, viewed 177866 times

1 概述

创建型模式,提供了一种创建对象的最佳实践。工厂方法模式(Factory Method Pattern)的核心思想,是通过统一的工厂类来获取对象,而不需要调用类的构造方法。

2 优点

  1. 可以将类的实例化过程延缓到子类。调用者无需知道接口/抽象类的具体实现是什么,利用工厂方法即可获取类的实例,降低与调用者的耦合度。
  2. 隐藏类的构造细节,降低类创建的复杂度,提高程序可读性。
  3. 可以根据不同环境/参数,从工厂构造不同的方法。

3 案例

有一个饭店的接口,饭店里有厨师和服务员。我们定义KFCPizzaHut两个饭店:

interface Restaurant {
    void getCook();
    void getWaiter();
}

public class KFC implements Restaurant {

    @Override
    public void getCook() {
        System.out.println("I'm KFC cook.");
    }

    @Override
    public void getWaiter() {
        System.out.println("I'm KFC waiter.");
    }
}

class PizzaHut implements Restaurant {

    @Override
    public void getCook() {
        System.out.println("I'm PizzaHut cook.");
    }

    @Override
    public void getWaiter() {
        System.out.println("I'm PizzaHut waiter.");
    }
}

3.1 工厂类型1

再定义一个工厂方法RestaurantFactory,从工厂中,很容易就能根据类型获取对应的饭店:

public class Test {
    public static void main(String[] args) {
        RestaurantFactory factory = new RestaurantFactory();
        Restaurant kfc = factory.createRestaurant(RestaurantFactory.RestaurantType.KFC);
        Restaurant pizzaHut = factory.createRestaurant(RestaurantFactory.RestaurantType.PizzaHut);
        kfc.getCook();
        pizzaHut.getWaiter();
    }
}

class RestaurantFactory {
    enum RestaurantType {
        KFC, PizzaHut
    }

    Restaurant createRestaurant(RestaurantType type) {
        switch (type) {
            case KFC: return new KFC();
            case PizzaHut: return new PizzaHut();
            default: System.out.format("Invalid restaurant %s", type); return null;
        }
    }
}

输出:

I'm KFC cook.
I'm PizzaHut waiter.

UML:
UML for factory type1

比如Spring中的BeanFactory使用的就是这种模式:getBean方法用Bean类型/名字作为参数,返回对应的Bean
JDK中的Calendar类,也是用的这种模式:

public static Calendar getInstance(TimeZone zone, Locale aLocale) {
    ...
    // 根据参数创建不同的Calendar实例
    if (aLocale.hasExtensions()) {
        String caltype = aLocale.getUnicodeLocaleType("ca");
        if (caltype != null) {
            switch (caltype) {
            case "buddhist":
            cal = new BuddhistCalendar(zone, aLocale);
                break;
            case "japanese":
                cal = new JapaneseImperialCalendar(zone, aLocale);
                break;
            case "gregory":
                cal = new GregorianCalendar(zone, aLocale);
                break;
            }
        }
    }
    ...
}

如果实例类型相对固定,那么上述模式能很好的满足需求。但是如果实例类型不确定,那么每当需要新增类型的时候,都需要改动原先的方法,对开闭原则遵循得不好。于是有了第二种类型。

3.2 工厂类型2

依然是饭店的例子,我们通过如下方式定义工厂:

public class Test {
    public static void main(String[] args) {
        KFCFactory kfcFactory = new KFCFactory();
        PizzaHutFactory pizzaHutFactory = new PizzaHutFactory();
        Restaurant kfc = kfcFactory.createRestaurant();
        Restaurant pizzaHut = pizzaHutFactory.createRestaurant();
        kfc.getCook();
        pizzaHut.getWaiter();
    }
}

class KFCFactory {
    Restaurant createRestaurant() {
        return new KFC();
    }
}

class PizzaHutFactory {
    Restaurant createRestaurant() {
        return new PizzaHut();
    }
}

输出:

I'm KFC cook.
I'm PizzaHut waiter.

UML:
UML for factory type2

上述方式,每新增一个类别,只需要新增一个对应的工厂即可,原先的工厂方法以及实例无需做任何修改。如LoggerFactory)就是这种类型的工厂模式:

public static Logger getLogger(String name) {
    // getLogger最终是委托给ILoggerFactory去做的。
    // 新增Logger获取方式,只需新增ILoggerFactory的实现类,扩展性很强。
    ILoggerFactory iLoggerFactory = getILoggerFactory();
    return iLoggerFactory.getLogger(name);
}

但是这种方式,对每一种类别,都要有一个工厂类,复杂度相对较高。实际中,还是第一种类型使用比较频繁。

4 总结

工厂方法模式是使用很广泛的一种创建型模式,几乎能在所有的开源框架中见到。很典型的特点就是,工厂类以Factory字样结尾:-)。

文中例子的github地址

Responses
  1. 小额投资可以快速带来大量美元。
    链接 - https://moneylinks.page.link/6SuK

    Reply
  2. dvd 通販 新品 dvd 通販 安い dvd 通販サイト DVD買取 dvd 通販 激安 nhk dvd 購入 アニメ dvd 安く買う ドラマdvd 人気 dvd 海賊版

    Reply
  3. 没有财务技能? 让机器人为你make钱。
    链接 - http://1c-met.ru/bitrix/rk.php?id=2&event1=banner&event2=click&goto=http://go.tiptopko3.com/096s

    Reply
  4. 使$1000从$1在几分钟内。 现在启动金融机器人。
    链接 - https://plbtc.page.link/aF8A

    Reply
  5. 即使是一个孩子知道如何使$100今天这个机器人的帮助。
    链接 - https://plbtc.page.link/aF8A

    Reply
  6. 韓劇dvd dvd購買 陸 劇 DVD 日本動畫DVD 日劇DVD 電視劇 DVD 歐美劇DVD DVD郵購 DVD 貨到付款

    Reply
  7. 点击机器人可以为您带来数千美元。
    链接 - https://plbtc.page.link/Dw1j

    Reply
  8. 学习如何使数百背上的每一天。
    链接 - https://24crypto.de/bitcoin-trading-options.php

    Reply
  9. 额外的收入现在可用于世界各地的任何人。
    链接 - https://24crypto.de/bitcoin-bonus-no-deposit.php

    Reply
  10. 一美元是什么,但它可以成长为100美元在这里。
    链接 - https://24crypto.de/cryptotrade-bitcoin-investment-platform-nulled.php

    Reply
  11. 推出最好的投资工具,今天开始making钱。
    链接 - https://24crypto.de/btc-markets-change-email-address.php

    Reply
  12. 了解财务独立的最快方法。
    链接 - https://24crypto.de/is-bitcoin-traded-publicly.php

    Reply
  13. 金融机器人是网络中最有效的金融工具!
    链接 - https://24crypto.de/trade-bitcoin-using-coinsph.php

    Reply
  14. 不用担心,如果你被解雇了。 在线工作。
    链接 - https://24crypto.de/bitcoin-brokers-review.php

    Reply
  15. 每个人的额外收入。
    链接 - https://24crypto.de/best-times-to-day-trade-bitcoin.php

    Reply
  16. 第一借錢網擁有全台最多的借錢資訊

    https://168cash.com.tw/

    Reply
  17. 使用这个机器人是让你致富的最佳方式。
    链接 - https://24crypto.de/how-does-trading-work-with-bitcoin.php

    Reply
  18. 即使是一个孩子知道如何make钱。 这个机器人是你所需要的!
    链接 - https://24crypto.de/trade-forex-with-bitcoin.php

    Reply
  19. XYZ專業光碟教學網站

    http://xyz.net.tw/

    Reply
  20. 即使是一个孩子知道如何使$100今天。
    链接 - https://24crypto.de/market-efficiency-bitcoin.php

    Reply
  21. 需要现金? 启动这个机器人,看看它可以。
    链接 - https://aicrypto4.de/btc-demon.php

    Reply
  22. 歐客佬精品咖啡

    https://blog.oklaocoffee.tw/

    Reply
  23. XYZ 壯陽藥春藥專賣店 大量購買有優惠

    https://man-r20.com/

    Reply
  24. 金融机器人是你的成功公式被发现。 了解更多关于它。
    链接 - https://bitcoinlife24.de/bitcoin-trading-profitable.php

    Reply
  25. 使用这个机器人是让你致富的最佳方式。
    链接 - https://bitcoinlife24.de/hitbtc-coinmarketcap.php

    Reply
  26. 对于退休人员最好的在线工作. 让你的老年人富有。
    链接 - https://cryptoncoins.de/quora-bitcoin-trading.php

    Reply
  27. 金融机器人不断为您带来的钱,而你睡觉。
    链接 - https://crypmoney.de/bitcoins-traden-lernen.php

    Reply
  28. 自动机器人是财务独立的最佳起点。
    链接 - https://allcryptocoins.de/best-bitcoin-broker-in-south-africa.php

    Reply
  29. XYZ 壯陽藥春藥專賣店 大量購買有優惠

    https://man-r20.com/

    Reply
  30. XYZ 國中基測

    http://xyz.net.tw/

    Reply
  31. 我们已经找到了致富的最快方法。 在这里找到它。
    链接 - http://t-protex.de/bitcoin-qt-walletdat.php

    Reply
  32. 查看最新的方式来make取梦幻般的利润。
    链接 - http://ute-strohner.de/ranking-bitcoin-mining.php

    Reply
  33. 金融机器人是你未来的财富和独立性。
    链接 - http://stuntszene.de/cara-mencairkan-uang-bitcoin.php

    Reply
  34. 如果你使用这个机器人在线工作可以真正有效。
    链接 - http://gasthausamflughafen.de/bitcointalk-bitcoin-private.php

    Reply
  35. 歐客佬精品咖啡

    https://blog.oklaocoffee.tw/

    Reply
  36. 对于退休人员最好的在线工作. 让你的老年人富有。
    链接 - http://stuntszene.de/split-bitcoin-into-bitcoin-cash.php

    Reply
  37. 立即将1美元变成100美元。 使用金融机器人。
    链接 - http://timberlandschuheherren.de/bitcoin-35000.php

    Reply
  38. 现在在网上making钱更容易。
    链接 - http://feuerwehr-matzenbach.de/bitcoin-materia-fantastico.php

    Reply
  39. XYZ 壯陽藥春藥專賣店 大量購買有優惠

    https://man-r20.com/

    Reply
  40. XYZ 壯陽藥春藥專賣店 大量購買有優惠

    https://man-r20.com/

    Reply