【設計模式】工廠系列-FactoryMethod,AbstractFactory,Spring IOC

語言: CN / TW / HK

theme: channing-cyan

今天來說一下設計模式的工廠系列。這一系列主要包括工廠方法、抽象工廠,最後再看看Spring的利器IOC。

何為工廠

任何可以產生物件的方法或類,都可以叫做工廠。

so,單例模式 getInstance 也是一種工廠。

那為什麼有了new之後,還要工廠呢? - 靈活控制生產過程; - 許可權、日誌、管理 - ...

下面我就用生產防護用品來舉例說明為什麼要使用工廠

  • 任意定製口罩

    繼承ProtectiveEquip

  • 任意定製生產過程

    ProtectiveEquip xxxFactory.create()

  • 任意定製產品一族

工廠方法

作為有需求的客戶端Clientnew一個口罩出來:

java public class Client { public static void main(String[] args) { FaceMask fm = new FaceMask(); fm.protect(); } }

定義一個口罩類:

java public class FaceMask { public void protect() { System.out.println("face masks don't let the virus enter"); } }

如果client自我保護意識比較強,還需要定製一雙防護手套,那麼就需要再定義一個防護手套類HandMask,也提供一個protect方法;

client需求又升級了,他還要防護衣服ProtectiveSuit...

如果一直這樣new下去,那就有點不太好了,要是有工廠能生產就好了。

工廠來了:

```java /* * 簡單工廠 生產防護用品 * 簡單工廠的可擴充套件性不好,比如需要造新的防護用品的時候,需要加方法 * @author 行百里者 / public class SimpleProtectiveEquipFactory {

FaceMask createFaceMask() {
    return new FaceMask();
}

HandMask createHandMask() {
    return new HandMask();
}

//如果還需要生產其他防護用品,就接著寫createXXX方法

} `` 這就是簡單工廠`,能夠生產你需要的東西,前提是你得往這個工廠裡寫方法。這也不太方便啊,而且不好擴充套件。

那就每個工廠各司其職,自己生產自己的東西,口罩工廠生產口罩,手套工廠生產手套。。。

口罩工廠: java public class FaceMaskFactory { FaceMask create() { System.out.println("業務邏輯..."); return new FaceMask(); } } 防護手套工廠: java public class HandMaskFactory { HandMask create() { System.out.println("業務邏輯..."); return new HandMask(); } } 等等,需要造什麼,就建立什麼工廠。

客戶Client這裡:

java public class Client { public static void main(String[] args) { FaceMaskFactory factory = new FaceMaskFactory(); //保護我 factory.create().protect(); } } 由此,可以看出,工廠方法既能滿足任意制定防護工具,又能任意制定生產過程——create方法由你的工廠實現。

image.png

那麼,如果我是個大廠,想搞宇宙化戰略,既能生產正常人類的防護用品,又能生產其他種族的防護用品,比如漂亮國的人,火星人等等的防護用品,我該怎麼辦?

像工廠方法那樣建造很多個工廠也能實現,但是有點繁瑣了。。。

image.png

抽象工廠

如何解決上面的宇宙化戰略問題呢?建造生產產品一族的工廠,我們稱之為抽象工廠

剛才提到的產品一族,比如HumanFactory生產防護用品是FaceMask、食物是RiceUsaFactory生產防護用品是Rags、食物是Junk等等

HumanFactory是正常人類一族; UsaFactory漂亮國一族。

他們各自生產本族的不同類別的產品。

這時我們可以弄一個抽象工廠叫BaseFactory,它能生產食物、防護用品:

java public abstract class BaseFactory { abstract Food createFood(); abstract ProtectiveEquip createProtectiveEquip(); }

具體的產品族分別實現這個抽象工廠:

```java public class HumanFactory extends BaseFactory { @Override Food createFood() { //生產大米飯 return new Rice(); }

@Override
ProtectiveEquip createProtectiveEquip() {
    //生產口罩
    return new FaceMask();
}

} ```

```java public class UsaFactory extends BaseFactory { @Override Food createFood() { //生產Junk Food return new Junk(); }

@Override
ProtectiveEquip createProtectiveEquip() {
    //生產破布條
    return new Rags();
}

}

```

image.png

一個抽象的工廠,可以生產兩個抽象的產品;兩個具體的工廠分別生產自己的產品。

如此,便可實現可以定製任意產品族

這就是抽象工廠模式

抽象工廠模式是工廠方法模式的升級版本,在有多個業務品種、業務分類時,通過抽象工廠模式產生需要的物件是一種非常好的解決方式。

image.png

我們來看看抽象工廠的通用原始碼,首先有兩個互相影響的產品線(也叫做產品族),例如製造汽車的左側門和右側門,這兩個應該是數量相等的——兩個物件之間的約束,每個型號的車門都是不一樣的,這是產品等級結構約束的。

Spring Bean工廠

Spring IOC其實也是一種工廠---生產各種Bean的工廠,這裡我們只簡單說一下它的用法。

pom.xml引入Spring的包

```

org.aspectj aspectjweaver 1.9.5

org.springframework spring-core 5.2.6.RELEASE

org.springframework spring-context 5.2.6.RELEASE

org.springframework spring-aop 5.2.6.RELEASE ```

在Spring配置檔案app.xml中定義想要被Spring託管的類:

<bean id="rice" class="com.traveler100.dp.abstractfactory.Rice"></bean>

Client可直接使用:

ApplicationContext ctx = new ClassPathXmlApplicationContext("app.xml"); Rice rice = (Rice) ctx.getBean("rice"); rice.printName();

牛逼不?省去了很多程式碼吧,什麼xxxFactory啊,什麼繼承啊等等,都不用我們自己去寫了,我們可以把很多類直接扔給Spring,讓它幫我們例項化,把Bean的控制權交給Spring,這就是所謂的控制反轉Spring IOC

我們可以把它看成造各種Bean的工廠,也就是Spring Bean工廠