你真的會用簡單工廠模式嗎?

NO IMAGE

前言

在項目中經常會碰到工廠模式,不光在項目中有在閱讀源碼的時候也一定少不了工廠模式。在我們上上一篇文章分佈式定時任務Quartz中創建觸發器也是通過Quartz所提供的工廠來創建實例。可見工廠模式有多方便多常用。本文主要講解簡單工廠模式。

工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。

在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,並且是通過使用一個共同的接口來指向新創建的對象。

介紹

工廠模式有三種分為簡單工廠模式、廠方法模式、抽象工廠模式其中簡單工廠模式並不屬於
GOF所提出的23種設計模式之中,簡單工廠模式其實更像是一種習慣。在設計模式之中工廠模式是屬於創建型。

簡單工廠模式

定義

簡單工廠模式到底啥時候使用,還有就是為什麼要使用簡單工廠模式呢?
首先在上面我們說了工廠模式是創建型,在介紹的時候也說了它提供了一種創建對象的最佳方式也就是說簡單工廠模式的定義就是由一個工廠對象來決定創建那種產品實例。其次就是什麼時候使用簡單工廠模式,首先現在有這樣一個場景。小明決定去賣車,一種是奔馳一種是奧迪:

        /**
* 小明要賣車
*/
/**
* 先生產奧迪
*/
AudiCar audiCar = new AudiCar();
/**
* 在生產奔馳
*/
MercedesCar mercedesCar = new MercedesCar();

然後發現自己生產成本太高,小明還要自己盯著各種細節。這並不是小明想要的他只想賺個差價。
這個時候就可以使用簡單工廠模式來幫助小明因為創建的對象比較少,然後工廠只需要知道需要什麼就返回什麼然後也不需要關心關鍵邏輯的時候就可以使用簡單工廠模式這就是簡單工廠模式的使用場景,那我使用了簡單工廠模式有啥優點呢?從上面簡單的例子就可以知道客戶端可以免除創建對象的責任直接交給工廠進行創建然後就是只需要知道傳入的參數就可以獲取到所需要的參數而且無需知道創建細節這不正是小明想要的嗎?hahaha。注意:在強調一下簡單工廠模式並不屬於23種設計模式,它只是一種編碼風格和實現

案例

看完上面你就已經知道什麼時候用簡單工廠模式還有就是知道了它的優點和使用場景,那麼現在就開始實戰。在創建之前要知道簡單工廠模式有一下幾種角色。

你真的會用簡單工廠模式嗎?

然後定義一個抽象產品接口。

/**
* @Author :luomengsun.
* @Date :Created in 13:26 2020/1/5
* @Description:
*/
public interface Car {
/**
* 輸出簡單信息
*/
void printInfo();
}

一開始定義的Audi和Mercedes就是我們的具體產品,改造一下

public class AudiCar implements Car {
@Override
public void printInfo() {
System.out.println("生產了奧迪");
}
}
public class MercedesCar  implements Car{
@Override
public void printInfo() {
System.out.println("生產了奔馳");
}
}

它們都實現了我們的抽象產品接口(也可以使用抽象類,但是儘量使用面向接口),現在定義工廠類。

public class CarFactory {
public Car getCarFactory(String str){
Car car = null;
if("audi".endsWith(str)){
car = new AudiCar();
}else if("mercedes".equals(str)){
car = new MercedesCar();
}else {
System.out.println("沒有定義產品");
}
return car;
}
}

然後我們就在測試客戶端裡面通過工廠類來創建汽車。

public class TestClient {
public static void main(String[] args) {
/**
* 小明通過汽車工廠生產車
*/
CarFactory carFactory = new CarFactory();
/**
* 先生產奧迪
*/
Car car = carFactory.getCarFactory("audi");
car.printInfo();
}
}

這個時候控制檯輸出生產了奧迪
UML類圖:

你真的會用簡單工廠模式嗎?

對比

上面就實現了簡單工廠模式,我們對比一下最開始的實現,在引入簡單工廠模式之後客戶端需要什麼就直接告訴工廠就行,根本不需要我們關心具體的細,實質上也就是對創建對象進行了封裝。如果在舉一個例子的話就比如我們去肯德基去吃飯,我們想要吃薯條直接在前臺點就行,你會關心薯條是怎麼生產的嗎?而且在你點薯條之前你肯定是知道有這個產品的,不然你怎麼去下單?

缺點

上面把簡單工廠模式誇了一大堆,那它都有啥缺點呢?你別說缺點還真的有,首先看一下我們的工廠類。

public class CarFactory {
public Car getCarFactory(String str){
Car car = null;
if("audi".endsWith(str)){
car = new AudiCar();
}else if("mercedes".equals(str)){
car = new MercedesCar();
}else {
System.out.println("沒有定義產品");
}
return car;
}
}

如果這個時候我想要增加寶馬怎麼辦,肯定要先創建一個具體產品,然後在修改工廠類的判斷邏輯,這樣就違反了開閉原則。而且工廠類集中了所有實例的創建邏輯,違反了高內聚低耦合的原則。
那麼有沒有一種方法可以不修改工廠類裡面的邏輯的方法嗎?這個肯定是有的,我們可以使用反射來創建具體的產品。修改一下工廠類:

public class CarFactory {
public Car getCarFactory(Class c){
Car car = null;
try {
car = (Car) Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return car;
}
}

代碼實例

上面清楚了簡單工廠模式接下來看一下簡單工廠模式實際種的運用。
在JDK中處理時間不光有Date這個類還有Calendar類,在Calendar類中就使用了簡單工廠模式。看一下getInstance()方法裡面的實現

   public static Calendar getInstance()
{
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}

它在裡面調用了createCalendar方法然後在createCalendar方法裡面有以下實現,是不是很熟悉

你真的會用簡單工廠模式嗎?

這裡就是運用我們一開始實現的簡單工廠模式

總結

簡單工廠模式類型是創建型,但是它不屬於23種設計模式,他只是一種實現方法。運用場景創建的對象比較少,然後工廠只需要知道需要什麼就返回什麼然後也不需要關心關鍵邏輯的時候就可以使用簡單工廠模式,優點:客戶端可以免除創建對象的責任直接交給工廠進行創建還有就是
只需要知道傳入的參數就可以獲取到所需要的參數而且無需知道創建細節。缺點就是違背了開閉原則還違反了高內聚低耦合的原則。

最後

開胃小菜已經奉上,下一篇來看工廠模式更高級的實現。歡迎關注轉發,最後在附一個簡單工廠模式的邏輯導圖

你真的會用簡單工廠模式嗎?

相關文章

跨域詳解(HTTPCORS)

大廠面試中遇到的幾十道webpack與react面試題

從業務場景角度談數組去重

在iOS中使用OpenGLES實現繪畫板