設計模式是一套被反覆使用,多數人知曉,通過分類編目的,代碼設計的總結,也能夠說是前人的智慧結晶。學習設計模式能讓咱們對一些應用場景使用相同的套路達到很好的效果,我會不定時更新一些本身對設計模式的理解的文章,從定義,實現,應用場景來講說設計模式,今天我要說的對象是工廠模式
一:定義
什麼是工廠?工廠模式是咱們最經常使用的實例化對象模式了,是用工廠方法代替new操做的一種模式,工廠模式屬於建立型模式:對象實例化的模式,用於解耦對象的實例化過程。簡單的說工廠模式就是用來建立對象的,傳統的對象建立方法是new,有了工廠模式以後,某些特定的對象咱們不須要在每一個使用的地方都使用new,而是把對象的建立放在一個或者一組統一的類中,從達到解耦的目的。
二:實現
從實現上來講,工廠模式分爲三種,簡單工廠模式,工廠模式,抽象工廠模式,簡單工廠模式並不屬於23中設計模式的範疇,由於它對解耦的實現不理想,同時不符合開不原則,不過簡單工廠模式是工廠模式的一種簡易實現,能夠爲學習工廠模式提供一個好的開端。在展現具體的代碼以前,咱們先來講說一個類的做用,咱們提供一個類,無非是但願經過這個類來幫助咱們來實現一些功能,而工廠模式中生產出來的類,都具備相同的功能,只不過這個功能的具體實現可能不同,
1.簡單工廠模式
簡單工廠模式的設計思想很是簡單,就像一個小型的工廠,能生產幾種特定的產品,小工廠通常都很本分,不敢太冒進,只有在收到訂單(接收到指令)的時候纔敢生產產品,若是要擴大業務,生產新的產品,必須對工廠進行改造,小本生意,原本就沒有太多冗餘的空間。小工廠呢,一般是有了某種渠道,得到了某幾種產品的生產權,而後才針對真幾種產品建立了工廠,因此,在工廠以前,產品是肯定的,並且產品的類型還不能區別太大,通常是某種大類產品下的幾個分類,這樣這個工廠的不少設備模具均可以共用,節約成本,下面咱們就以代碼的形式來體現工廠
首先,確認產品,確認產品以前,還要確認產品的類型,方便購買一些通用的設備咱們的產品就是輪胎,每款輪胎上都有一些介紹信息,標識當前輪胎的種類,雖然輪胎的種類不少,功能不一,可是介紹信息的格式都同樣
abstract class Tyre{
abstract void desc();
}
//這是奔馳的輪胎
class BenzTyre extends Tyre{
@Override
void desc() {
System.out.println("這是奔馳的輪胎");
}
}
//這是寶馬的輪胎
class BMWTyre extends Tyre{
@Override
void desc() {
System.out.println("這是寶馬的輪胎");
}
}
//這是奧迪的輪胎
class AudiTyre extends Tyre{
@Override
void desc() {
System.out.println("這是奧迪的輪胎");
}
}
既然已經確認了訂單,那麼接下來咱們能夠開始建設工廠了
class TyreFactory{
public static Tyre createTyre(String TyreName){
switch (TyreName){
case "Benz":
//接受到生產奔馳輪胎的指令
return new BenzTyre();
case "BMW":
//接受到生產寶馬輪胎的指令
return new BMWTyre();
case "Audi":
//接受到生產生產奧迪輪胎的指令
return new AudiTyre();
default:
return null;
}
}
}
下面模擬客戶下單,工廠生產輪胎,拿到輪胎後確認產品的過程
class Clients{
public static void main(String[] fdfd){
//工廠接到指令生產了一個奔馳的輪胎
Tyre tyre=TyreFactory.createTyre("Benz");
//客戶拿到輪胎後看一下標籤
tyre.desc();
//工廠接到指令生產了一個寶馬的輪胎
tyre=TyreFactory.createTyre("BMW");
//客戶拿到輪胎後看一下標籤
tyre.desc();
//工廠接到指令生產了一個奧迪的輪胎
tyre=TyreFactory.createTyre("Audi");
//客戶拿到輪胎後看一下標籤
tyre.desc();
}
}
總結:簡單工廠模式有必定的優勢,對於客戶來講,只須要下達一個指令,就能夠獲取到本身須要的產品,而不用去關心產品的生產過程。但也有很明顯的缺點,就如今的工廠來講,只符合生產現有產品的要求,當有新產品添加的時候,必須對如今的工廠進行改造,改造必然須要拆裝,拆裝的過程有致使整個工廠倒塌的風險。在代碼的角度來講,工廠模式符合里氏替代原則,在必定程度上解決了耦合問題,可是同時,它有違反了開閉原則。當一個新的產品須要被添加的時候,必須對工廠類進行改造。那麼,是否有辦法解決這個問題呢,答案固然是有的,那就是工廠模式
2.工廠模式
工廠模式是簡單工廠模式的進階版,咱們知道,簡單工廠模式的主要缺點是不符合開閉原則,當新產品被添加的時候,須要更改工廠類,因此,在工廠模式中,咱們專門對工廠類進行了改造。爲了生產新的產品不改造工廠類,咱們抽象工廠類,也就是把工廠類變成一個抽象的對象,不進行產品的生產,把產品的生產過程交給它的子類進行,當有新的產品添加的時候,只須要添加新的子類便可,不涉及已有代碼的更改。固然,這些子類,其實也是一個工程類,只不過是只針對某一種產品的工程類,下面展現代碼抽象原有的工廠類,只定義應該生產的產品類型,而再也不進行具體產品的生產設計模式
abstract class TyreFactory{
//提取子類必須實現的方法
abstract Tyre createTyre();
}
創造寶馬輪胎廠,只生產寶馬輪胎
class BMWTyreFactory extends TyreFactory{
//寶馬輪胎廠生產寶馬輪胎
@Override
Tyre createTyre() {
return new BMWTyre();
}
}
創造奔馳輪胎廠,只生產奔馳輪胎
class BenzTyreFactory extends TyreFactory{
//奔馳輪胎廠生產奔馳輪胎
@Override
Tyre createTyre() {
return new BenzTyre();
}
}
創造奧迪輪胎廠,只生產奧迪輪胎
class AudiTyreFactory extends TyreFactory{
//奧迪輪胎廠生產奧迪輪胎
@Override
Tyre createTyre() {
return new AudiTyre();
}
}
再看調用
class Clients{
public static void main(String[] fdfd){
//奔馳工廠生產了一個奔馳的輪胎
Tyre tyre=new BenzTyreFactory().createTyre();
//客戶拿到輪胎後看一下標籤
tyre.desc();
//寶馬工廠生產了一個寶馬的輪胎
tyre=new BMWTyreFactory().createTyre();
//客戶拿到輪胎後看一下標籤
tyre.desc();
//奧迪工廠生產了一個奧迪的輪胎
tyre=new AudiTyreFactory().createTyre();
//客戶拿到輪胎後看一下標籤
tyre.desc();
}
}
總結:工廠模式很好的解決了簡單工廠模式不符合開閉原則的缺點,在工廠模式中新增一個產品,只須要增大產品類和對應的工廠類,不會涉及原有代碼的更改,符合開閉原則,擴展不會對原有的功能產生影響,一樣工廠模式也符合里氏替代原則。可是,工廠模式並不完美,咱們注意到,工廠模式只能生產一個類別的產品。好比,咱們上面的輪胎工廠,只能生產輪胎,若是想生產內膽呢,並且內膽和輪胎每每都是配套使用的,寶馬的輪胎不可能配用奔馳的內膽,對於這種配套的產品(對象),爲了避免混淆,有沒有一個好的解決方案呢,答案固然是有的,那就是抽象工廠模式
3.抽象工廠模式
抽象工廠模式最重要的思想就是引入了產品族的感念,能夠理解爲配套或者或有關聯的一系列產品(對象),組成一個產品族,使用這個工廠再也不生產單一的產品,而是生產一整套的產品,好比咱們的輪胎工廠,直接生產配套的輪胎和內膽,而不用擔憂奔馳的輪胎用了寶馬的內膽。那麼,咱們須要添加一個新的產品:內膽,因爲奔馳,寶馬,奧迪的內膽都不同,因此要獨立建立這三種車的內膽,而且要在原來頂層工廠類中添加一個生產內膽的抽象方法,而對應的這三種車的工廠類在生產輪胎的同時要配套的生產內膽
//建立內膽產品類
abstract class Innertube{
//內膽的標籤,顯示內膽的出身信息
abstract void innertubeDesc();
}
//奔馳內膽
class BenzInnertube extends Innertube{
@Override
void innertubeDesc() {
System.out.println("這是奔馳的內膽");
}
}
//寶馬內膽
class BMWInnertube extends Innertube{
@Override
void innertubeDesc() {
System.out.println("這是寶馬的內膽");
}
}
//奧迪內膽
class AudiInnertube extends Innertube{
@Override
void innertubeDesc() {
System.out.println("這是奧迪的內膽");
}
}
//工廠類的改變
abstract class Factory{
//生產輪胎的方法
abstract Tyre createTyre();
//生產內膽的方法
abstract Innertube createInnertube();
}
//奔馳
class BMWFactory extends Factory{
//寶馬輪胎廠生產寶馬輪胎
@Override
Tyre createTyre() {
return new BMWTyre();
}
//寶馬輪胎廠生產寶馬內膽
@Override
Innertube createInnertube() {
return new BMWInnertube();
}
}
//寶馬
class BenzFactory extends Factory{
//奔馳輪胎廠生產奔馳輪胎
@Override
Tyre createTyre() {
return new BenzTyre();
}
//奔馳輪胎廠生產奔馳內膽
@Override
innertube createInnertube() {
return new BenzInnertube();
}
}
//奧迪
class AudiFactory extends Factory{
//奧迪輪胎廠生產奧迪輪胎
@Override
Tyre createTyre() {
return new AudiTyre();
}
//奧迪輪胎廠生產奧迪內膽
@Override
Innertube createInnertube() {
return new AudiInnertube();
}
}
//模擬客戶下單
class Clients{
public static void main(String[] fdfd){
//向奔馳工廠下一個單,生產一套奔馳專用的輪胎和內膽
BenzFactory benzFactory=new BenzFactory();
//生產
Tyre tyre=benzFactory.createTyre();
Innertube innertube=benzFactory.createInnertube();
//客戶拿到輪胎後看一下標籤
tyre.desc();
innertube.innertubeDesc();ide
//向寶馬工廠下一個單,生產一套寶馬專用的輪胎和內膽
BMWFactory bmwFactory=new BMWFactory();
//生產
tyre=bmwFactory.createTyre();
innertube=bmwFactory.createInnertube();
//客戶拿到輪胎後看一下標籤
tyre.desc();
innertube.innertubeDesc();學習
//向奧迪工廠下一個單,生產一套奧迪專用的輪胎和內膽
AudiFactory audiTyreFactory=new AudiFactory();
//生產
tyre=audiTyreFactory.createTyre();
innertube=audiTyreFactory.createInnertube();
//客戶拿到輪胎後看一下標籤
tyre.desc();
innertube.innertubeDesc();
}
}
不難看出,在工廠模式的基礎上,抽象工廠模式產品族感念的出現對於生產成套的產品(有聯繫的對象)提供了很大的便利,也符合開閉原則,里氏替代原則,不過也有它的缺陷:當在產品族(頂級工廠類)中須要添加一種新的產品的時候,全部的下級工廠都要進行修改。
三:應用場景
在什麼場景下應該使用工廠模式
1.一個系統不該當依賴於產品類實例如何被建立、組合和表達的細節
2.這個系統的產品有多於一個的產品族,而系統只消費其中某一族的產品。
3.同屬於同一個產品族的產品是在一塊兒使用的,這一約束必須在系統的設計中體現出來。
4.系統提供一個產品類的庫,全部的產品以一樣的接口出現,從而使客戶端不依賴於實現。設計