前言
最近在復習java設計模式中的工廠模式痰催。本來有一點小小的理解兜辞。感覺都寫的不錯,就是有點太零散了夸溶,最后還是決定自己手寫一把逸吵,加深印象。順便做個總結(jié)缝裁,以后復習起來也方便許多扫皱。
一、簡介
目前從網(wǎng)上了解工廠模式大體分為簡單工廠捷绑、工廠方法韩脑、抽象工廠等三種模式。工廠方法模式也可稱為工廠模式粹污,與抽象模式都是屬于GOF23種設計模式中的一員段多。可以大概理解為:簡單工廠進階變成了工廠方法壮吩,然后再進階成了抽象工廠进苍。難度逐步增加,也越來越抽象鸭叙。下面按先易到難逐個分析琅捏。
二、簡單工廠模式
屬于創(chuàng)建型模式递雀,又叫做靜態(tài)工廠方法模式,不屬于23種GOF設計模式之一蚀浆。是由一個工廠對象決定創(chuàng)建出哪一種產(chǎn)品類的實例缀程。實質(zhì)是由一個工廠類根據(jù)傳入的參數(shù),動態(tài)決定應該創(chuàng)建哪一個產(chǎn)品類(這些產(chǎn)品類繼承自一個父類或接口)的實例市俊。
作用:將“類實例化的操作”與“使用對象的操作”分開杨凑,讓使用者不用知道具體參數(shù)就可以實例化出所需要的“產(chǎn)品”類,從而避免了在客戶端代碼中顯式指定摆昧,實現(xiàn)了解耦撩满。
主要角色
工廠:負責實現(xiàn)創(chuàng)建所有實例的內(nèi)部邏輯,并提供一個外界調(diào)用的方法,創(chuàng)建所需的產(chǎn)品對象伺帘。
抽象產(chǎn)品:負責描述產(chǎn)品的公共接口
具體產(chǎn)品:描述生產(chǎn)的具體產(chǎn)品昭躺。
舉個簡單易懂的例子:
“假設”有一臺飲料機(工廠),可以調(diào)出各種口味的飲料(抽象產(chǎn)品)伪嫁,有三個按鈕(參數(shù))對應這三種飲料(具體產(chǎn)品)领炫。這時候你可以根據(jù)點擊按鈕來選擇你喜歡的飲料。
/**
* @ Product.java
* 抽象產(chǎn)品
* 描述產(chǎn)品的公共接口
*/
abstract class Product {
//產(chǎn)品介紹
abstract void intro();
}
/**
* @ AProduct.java
* 具體產(chǎn)品A
* (可以看成是一種飲料:可樂)
*/
public class AProduct extends Product{
@Override
void intro() {
System.out.println("可樂");
}
}
/**
* @ BProduct.java
* @具體產(chǎn)品B
* @(可以看成是一種飲料:奶茶)
*/
public class BProduct extends Product{
@Override
void intro() {
System.out.println("奶茶");
}
}
/**
* @ CProduct.java
* 具體產(chǎn)品C
* (可以看成是一種飲料:咖啡)
*/
public class CProduct extends Product{
@Override
void intro() {
System.out.println("咖啡");
}
}
Factory.java
/**
* 工廠
* 負責實現(xiàn)創(chuàng)建所有實例的內(nèi)部邏輯张咳,并提供一個外界調(diào)用的方法帝洪,創(chuàng)建所需的產(chǎn)品對象。
*/
public class Factory {
/**
* 供外界調(diào)用的方法
* (可以看成是對外提供的三種按鈕)
* @param type
* @return 產(chǎn)品實例
*/
public static Product getProduct(String type) {
switch (type) {
case "A":
return new AProduct();
case "B":
return new BProduct();
case "C":
return new CProduct();
default:
return null;
}
}
}
測試
public class Test {
public static void main(String[] args) {
//創(chuàng)建具體的工廠
Factory factory = new Factory();
//根據(jù)傳入的參數(shù)生產(chǎn)不同的產(chǎn)品實例
//(按下不同的按鈕脚猾,獲取飲料)
Product A = Factory.getProduct("A");
A.intro();
Product B = Factory.getProduct("B");
B.intro();
Product C = Factory.getProduct("C");
C.intro();
}
}
根據(jù)例子可以描述為:一個抽象產(chǎn)品類葱峡,可以派生出多個具體產(chǎn)品類。一個具體工廠類龙助,通過往此工廠的static方法中傳入不同參數(shù)砰奕,產(chǎn)出不同的具體產(chǎn)品類實例。
優(yōu)點:將創(chuàng)建使用工作分開泌参,不必關(guān)心類對象如何創(chuàng)建脆淹,實現(xiàn)了解耦;
缺點:違背“開放 - 關(guān)閉原則”沽一,一旦添加新產(chǎn)品就不得不修改工廠類的邏輯盖溺,這樣就會造成工廠邏輯過于復雜。
三铣缠、工廠方法模式
又稱工廠模式烘嘱、多態(tài)工廠模式和虛擬構(gòu)造器模式,通過定義工廠父類負責定義創(chuàng)建對象的公共接口蝗蛙,而子類則負責生成具體的對象蝇庭。一種常用的對象創(chuàng)建型設計模式,此模式的核心精神是封裝 類中不變的部分。
作用:將類的實例化(具體產(chǎn)品的創(chuàng)建)延遲到工廠類的子類(具體工廠)中完成捡硅,即由子類來決定應該實例化(創(chuàng)建)哪一個類哮内。
主要角色
抽象工廠:描述具體工廠的公共接口
具體工廠:描述具體工廠,創(chuàng)建產(chǎn)品的實例壮韭,供外界調(diào)用
抽象產(chǎn)品:負責描述產(chǎn)品的公共接口
具體產(chǎn)品:描述生產(chǎn)的具體產(chǎn)品
舉個簡單易懂的例子:
“假設”有各類的飲料機(抽象工廠)北发,可以調(diào)出各種的飲料(抽象產(chǎn)品)。但是一類飲料機(具體工廠)喷屋,只能生產(chǎn)一種飲料(具體產(chǎn)品)琳拨。如果你需要喝可樂,就需要買可樂飲料機屯曹。
產(chǎn)品:Product.java 狱庇、ProductA.java 惊畏、ProductB.java
/**
* @ Product.java
* 抽象產(chǎn)品
*/
abstract class Product {
//產(chǎn)品介紹
abstract void intro();
}
/**
* @ ProductA.java
* 具體產(chǎn)品A
*/
public class ProductA extends Product{
@Override
void intro() {
System.out.println("飲料A");
}
}
/**
* @ ProductB.java
* 具體產(chǎn)品B
*/
public class ProductB extends Product{
@Override
void intro() {
System.out.println("飲料B");
}
}
工廠:Factory.java、FactoryA.java 密任、FactoryB.java
/**
* @ Factory.java
* 抽象工廠
*/
abstract class Factory {
//生產(chǎn)產(chǎn)品
abstract Product getProduct();
}
/**
* @ FactoryA.java
* 具體工廠A
* 負責具體的產(chǎn)品A生產(chǎn)
*/
public class FactoryA extends Factory{
@Override
Product getProduct() {
return new ProductA();
}
}
/**
* @ FactoryB.java
* @具體工廠B
* 負責具體的產(chǎn)品B生產(chǎn)
*/
public class FactoryB extends Factory{
@Override
Product getProduct() {
return new ProductB();
}
}
測試:Test.java
public class Test {
public static void main(String[] args) {
//創(chuàng)建具體的工廠
FactoryA factoryA = new FactoryA();
//生產(chǎn)相對應的產(chǎn)品
factoryA.getProduct().intro();
FactoryB factoryB = new FactoryB();
factoryB.getProduct().intro();
}
}
根據(jù)例子可以描述為:一個抽象產(chǎn)品類颜启,可以派生出多個具體產(chǎn)品類。一個抽象工廠類批什,可以派生出多個具體工廠類农曲。每個具體工廠類只能創(chuàng)建一個具體產(chǎn)品類的實例。
優(yōu)點:
- 符合開-閉原則:新增一種產(chǎn)品時驻债,只需要增加相應的具體產(chǎn)品類和相應的工廠子類即可
- 符合單一職責原則:每個具體工廠類只負責創(chuàng)建對應的產(chǎn)品
缺點:
- 增加了系統(tǒng)的復雜度:類的個數(shù)將成對增加
- 增加了系統(tǒng)的抽象性和理解難度
- 一個具體工廠只能創(chuàng)建一種具體產(chǎn)品
四乳规、抽象工廠模式
定義:提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無須指定它們具體的類合呐;具體的工廠負責實現(xiàn)具體的產(chǎn)品實例暮的。
解決的問題:每個工廠只能創(chuàng)建一類產(chǎn)品(工廠方法模式)
抽象工廠模式與工廠方法模式最大的區(qū)別:抽象工廠中每個工廠可以創(chuàng)建多種類的產(chǎn)品;而工廠方法每個工廠只能創(chuàng)建一類
主要對象
抽象工廠:描述具體工廠的公共接口
具體工廠:描述具體工廠淌实,創(chuàng)建產(chǎn)品的實例冻辩,供外界調(diào)用
抽象產(chǎn)品族:描述抽象產(chǎn)品的公共接口
抽象產(chǎn)品:描述具體產(chǎn)品的公共接口
具體產(chǎn)品:具體產(chǎn)品
舉個簡單易懂的例子:(找了個不怎么好的比喻,看不懂得可以看相關(guān)推薦鏈接)
“假設”有各類的自動售賣機(抽象工廠)拆祈,可以出售各類食品(抽象產(chǎn)品族)恨闪。
有飲料、零食(抽象產(chǎn)品)放坏,比如常見的零食售賣機(具體工廠)咙咽,出售礦泉水與面包(具體產(chǎn)品)。
產(chǎn)品:Product淤年、ProductA钧敞、ProductB、ProductAa麸粮、ProductBb
/**
* @ Product.java
* 抽象產(chǎn)品族 (食品)
*/
abstract class Product {
//產(chǎn)品介紹
abstract void intro();
}
/**
* @ ProductA.java
* 抽象產(chǎn)品 (飲料)
*/
abstract class ProductA extends Product{
@Override
abstract void intro();
}
/**
* @ ProductB.java
* 抽象產(chǎn)品 (零食)
*/
abstract class ProductB extends Product{
@Override
abstract void intro();
}
/**
* @ ProductAa.java
* 具體產(chǎn)品 (礦泉水)
*/
public class ProductAa extends ProductA{
@Override
void intro() {
System.out.println("礦泉水");
}
}
/**
* @ ProductBb.java
* 抽象產(chǎn)品 (面包)
*/
public class ProductBb extends ProductB{
@Override
void intro() {
System.out.println("面包");
}
}
工廠:Factory.java溉苛、FactoryA.java
/**
* @ Factory.java
* 抽象工廠
*/
abstract class Factory {
//生產(chǎn)飲料
abstract Product getProductA();
//生產(chǎn)零食
abstract Product getProductB();
}
/**
* @ FactoryA.java
* 具體工廠A
* 負責具體的A類產(chǎn)品生產(chǎn)
*/
public class FactoryA extends Factory{
@Override
Product getProductA() {
//生產(chǎn)礦泉水
return new ProductAa();
}
@Override
Product getProductB() {
//生產(chǎn)面包
return new ProductBb();
}
}
測試:Test.java
public class Test {
public static void main(String[] args) {
//創(chuàng)建零食售賣機(具體工廠),
FactoryA factoryA = new FactoryA();
//獲取礦泉水與面包(具體產(chǎn)品)
factoryA.getProductA().intro();
factoryA.getProductB().intro();
}
}
?
根據(jù)實例可以描述為: 多個抽象產(chǎn)品類弄诲,每個抽象產(chǎn)品類可以派生出多個具體產(chǎn)品類愚战。一個抽象工廠類,可以派生出多個具體工廠類齐遵。 每個具體工廠類可以創(chuàng)建多個具體產(chǎn)品類的實例凤巨。.
優(yōu)點:
- 降低耦合
- 符合開-閉原則
- 符合單一職責原則
- 不使用靜態(tài)工廠方法,可以形成基于繼承的等級結(jié)構(gòu)洛搀。
缺點:難以擴展新種類產(chǎn)品
五、總結(jié)
角色不同:
- 簡單工廠:具體工廠佑淀、抽象產(chǎn)品留美、具體產(chǎn)品
- 工廠方法:抽象工廠、具體工廠、抽象產(chǎn)品谎砾、具體產(chǎn)品
- 抽象工廠:抽象工廠逢倍、具體工廠、抽象產(chǎn)品族景图、抽象產(chǎn)品较雕、具體產(chǎn)品
定義:
- 簡單工廠:由一個工廠類根據(jù)傳入的參數(shù),動態(tài)決定應該創(chuàng)建哪一個產(chǎn)品類(繼承自一個父類或接口)的實例挚币。
- 工廠方法:定義工廠父類負責定義創(chuàng)建對象的公共接口亮蒋,而子類則負責生成具體的對象
- 抽象工廠:提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無須指定它們具體的類妆毕;具體的工廠負責實現(xiàn)具體的產(chǎn)品實例慎玖。
對比:
- 工廠方法模式解決了簡單工廠模式的“開放 - 關(guān)閉原則
- 抽象工廠模式解決了工廠方法模式一個具體工廠只能創(chuàng)建一類產(chǎn)品
六、Demo地址
六笛粘、參考文檔
簡單工廠模式
http://www.reibang.com/p/e55fbddc071c
https://baike.baidu.com/item/%E7%AE%80%E5%8D%95%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/8801727
工廠方法模式
http://www.reibang.com/p/d0c444275827
抽象工廠模式
http://www.reibang.com/p/7deb64f902db
七趁怔、內(nèi)容推薦
CSDN: https://blog.csdn.net/cs_lwb/article/details/83999073
如果你覺得我寫的不錯或者對您有所幫助的話。不妨頂一個(點個贊唄)薪前,也方便以后復習
您的每個舉動都是對我莫大的支持
謝謝了H笈!示括!