引言
在實際的專案中,隨著我們的物件越來越多。管理的難度也越來越大。這時候怎麼辦呢?使用Spring容器呀!沒錯Spring容器也是用到了工廠設計模式。所以,我們今天就來學習一下工廠設計模式。
何為工廠設計模式?
根據名稱來理解,什麼是工廠?工廠就是有一堆流水線,來生產某一類的產品。假設:我們現在需要一瓶洗髮水,來呵護一下我們秀美的頭髮。於是我們親自動手做了一瓶海飛絲洗髮水。用了一段時間之後,我們發現自己的頭髮越來越少。這個時候,我們繼續一瓶 霸王防脫洗髮水,我們總不能每次都自己手動做一瓶,費時費力,還不見的效果好。那怎麼辦呢?當然讓工廠去負責生產洗髮水,我們直接透過購買獲得就OK。
工廠設計模式應用場景
在寫程式中,我們需要去建立某一類的一系列物件。比如:如上述,我們需要各種各樣的洗髮水,它們都同屬於洗髮水一類。
工廠設計模式的特徵:
- 呼叫者想建立物件,只需要呼叫對應的API即可。
- 擴充套件性強,需要增加一個產品,只需要擴充套件一個工廠類即可。
- 遮蔽產品的具體實現,呼叫者只關心產品的介面。
常見的工廠設計模式:
- 簡單工廠
- 工廠方法
- 抽象工廠
簡單工廠
簡單工廠,就是透過邏輯判斷,返回相應的物件。嚴格意義來講,如果我們要進行擴充套件的時候違背了開閉原則。工作中,不建議使用,耦合性太強了。
/**
* 洗髮水產品的介面
*/
interface Shampoo {
//... 一些洗髮水的特性
}
/**
* 海飛絲的洗髮水具體實現
*/
class HeadShouldersShampoo implements Shampoo {
//... 海飛絲洗髮水的特性
}
/**
* 霸王洗髮水的具體實現
*/
class BAWANGShampoo implements Shampoo {
//... 霸王洗髮水的特性
}
/**
* 清揚洗髮水的具體實現
*/
class ClearShampoo implements Shampoo {
//... 清揚洗髮水的特性
}
/**
* 洗髮水工廠
*/
class ShampooFactory {
// 提供對外獲取Shampoo的API
public static Shampoo getShampoo(String shampooName) {
// 獲取海飛絲洗髮水物件
if ("HeadShouldersShampoo".equalsIgnoreCase(shampooName)) {
return new HeadShouldersShampoo();
// 獲取霸王洗髮水物件
} else if ("BAWANGShampoo".equalsIgnoreCase(shampooName)) {
return new BAWANGShampoo();
// 獲取清揚洗髮水物件
} else if ("ClearShampoo".equalsIgnoreCase(shampooName)) {
return new ClearShampoo();
}
return null;
}
}
/**
* @ClassName : SimpleFactory
* @Description : 簡單工廠
*/
public class SimpleFactory {
public static void main(String[] args) {
// 獲取海飛絲洗髮水物件
Shampoo headShouldersShampoo = ShampooFactory.getShampoo("HeadShouldersShampoo");
if (headShouldersShampoo instanceof HeadShouldersShampoo){
System.out.println("獲取海飛絲洗髮水物件成功");
}
// 獲取霸王洗髮水物件
Shampoo bawangShampoo = ShampooFactory.getShampoo("BAWANGShampoo");
if (bawangShampoo instanceof BAWANGShampoo){
System.out.println("獲取霸王洗髮水物件成功");
}
// 獲取清揚洗髮水物件
Shampoo clearShampoo = ShampooFactory.getShampoo("ClearShampoo");
if (clearShampoo instanceof ClearShampoo){
System.out.println("獲取清揚洗髮水物件成功");
}
}
}
工廠方法
我們依然站在生活的角度去理解,簡單工廠,就是一個工廠,來生產各種各樣的洗髮水。但現實生活中,這樣有不操作是不現實的。我們一般會用一個工廠來生產海飛絲洗髮水,一個工廠來生產霸王洗髮水,一個工廠來生產清揚洗髮水。此時,我們如果要新增一個品牌的洗髮水,只需要增加一個工廠就好了。
// 洗髮水介面
interface Shampoo{
// ... 洗髮水共有的特性
}
/**
* 海飛絲的洗髮水具體實現
*/
class HeadShouldersShampoo implements Shampoo {
//... 海飛絲洗髮水的特性
}
/**
* 霸王洗髮水的具體實現
*/
class BAWANGShampoo implements Shampoo {
//... 霸王洗髮水的特性
}
/**
* 清揚洗髮水的具體實現
*/
class ClearShampoo implements Shampoo {
//... 清揚洗髮水的特性
}
/**
* 抽象出洗髮水工廠共有的特性
*/
interface ShampooFactory{
// 生產一瓶洗髮水
Shampoo getShampoo();
}
/**
* 海飛絲洗髮水工廠,主要負責生產海飛絲品牌的洗髮水
*/
class HeadShouldersShampooFactory implements ShampooFactory{
@Override
public Shampoo getShampoo() {
return new HeadShouldersShampoo();
}
}
/**
* 霸王洗髮水工廠,主要負責生產霸王品牌的洗髮水
*/
class BAWANGShampooFactory implements ShampooFactory{
@Override
public Shampoo getShampoo() {
return new BAWANGShampoo();
}
}
/**
* 清揚洗髮水工廠,主要負責生產清揚品牌的洗髮水
*/
class ClearShampooFactory implements ShampooFactory{
@Override
public Shampoo getShampoo() {
return new ClearShampoo();
}
}
/**
* @ClassName : FactoryMethod
* @Description : 工廠方法
*/
public class FactoryMethod {
public static void main(String[] args) {
// 獲取海飛絲洗髮水,首先獲取海飛絲的工廠,在獲取海飛絲洗髮水物件。
// 這裡肯定有小夥伴會疑惑,寧願 new 一個海飛絲工廠,為何不直接new 海飛絲物件呢?
// 其實結合單例設計模式,這個你可以把海飛絲工廠寫成單例,就不會重複的new 海飛絲工廠了。
Shampoo shampoo = new HeadShouldersShampooFactory().getShampoo();
if (shampoo instanceof HeadShouldersShampoo){
System.out.println("獲取海飛絲洗髮水物件成功");
}
// 獲取霸王洗髮水物件
Shampoo shampoo1 = new BAWANGShampooFactory().getShampoo();
if (shampoo1 instanceof BAWANGShampoo){
System.out.println("獲取霸王洗髮水物件成功");
}
// 獲取清揚洗髮水物件
Shampoo shampoo2 = new ClearShampooFactory().getShampoo();
if (shampoo2 instanceof ClearShampoo){
System.out.println("獲取清揚洗髮水物件成功");
}
}
}
抽象工廠
抽象工廠,這個名字起的都很抽象。不要好理解。比較官方一點的解釋:提供一個建立一系列相關或相互依賴物件的介面,而無需指定它們具體的類。讀起來都有點拗口。那就講一下本博主怎麼去理解?我們依然拿來生產一瓶洗髮水為例子。一瓶洗髮水,大致是由包裝和液體組成的,在實際的生產工作中,我們不可能序列的去生產,這樣太浪費時間了。於是乎,我們為了生產一瓶洗髮水,就最少開兩條流水線,一條生產液體,一條生產瓶子,又因為大部分的洗髮水,都是由和這個兩部分組成的,所以我們需要將生產液體和生產瓶子抽象出來,由每個品牌洗髮水自己的流水線來實現。
import java.util.List;
/**
* 定義洗髮水介面
*/
interface Shampoo {
// 設定洗髮水的液體
void setLiquid();
// 設定洗髮水的瓶子
void setBox();
}
/**
* 海飛絲的洗髮水具體實現
*/
class HeadShouldersShampoo implements Shampoo {
@Override
public void setLiquid() {
System.out.println("設定海飛絲洗髮水有液體");
}
@Override
public void setBox() {
System.out.println("設定海飛絲洗髮水的包裝");
}
//... 海飛絲洗髮水的特性
}
/**
* 霸王洗髮水的具體實現
*/
class BAWANGShampoo implements Shampoo {
@Override
public void setLiquid() {
System.out.println("設定霸王洗髮水液體");
}
@Override
public void setBox() {
System.out.println("設定霸王洗髮水的包裝");
}
//... 霸王洗髮水的特性
}
/**
* 清揚洗髮水的具體實現
*/
class ClearShampoo implements Shampoo {
@Override
public void setLiquid() {
System.out.println("設定清揚洗髮水液體");
}
@Override
public void setBox() {
System.out.println("設定清揚洗髮水的包裝");
}
//... 清揚洗髮水的特性
}
/**
* 洗髮水的液體介面,由各個品牌來實現
*/
interface Liquid {
}
/**
* 海飛絲洗髮水的具體實現類
*/
class HeadShouldersShampooLiquid implements Liquid {
}
/**
* 霸王洗髮水液體的具體實現類
*/
class BAWANGShampooLiquid implements Liquid {
}
/**
* 清揚洗髮水液體的具體實現類
*/
class ClearShampooLiquid implements Liquid {
}
/**
* 洗髮水包裝介面,有具體品牌的子類來實現
*/
interface Box {
}
/**
* 海飛絲的包裝
*/
class HeadShouldersShampooBox implements Box {
}
/**
* 霸王的包裝
*/
class BAWANGShampooBox implements Box {
}
/**
* 清揚的包裝
*/
class ClearingShampooBox implements Box {
}
/**
* 工廠介面
*/
interface ShampooFactory {
// 生產液體的流水線。
Liquid productionLiquid();
// 生產盒子的流水線。
Box productionBox();
// 生產洗髮水,將生產的液體和流水線組裝起來。
Shampoo getShampoo(Liquid liquid, Box box);
}
/**
* 海飛絲洗髮水的工廠
*/
class HearingShampooFactory implements ShampooFactory {
@Override
public Liquid productionLiquid() {
return new HeadShouldersShampooLiquid();
}
@Override
public Box productionBox() {
return new HeadShouldersShampooBox();
}
@Override
public Shampoo getShampoo(Liquid liquid, Box box) {
return new HeadShouldersShampoo();
}
}
/**
* 霸王洗髮水的工廠
*/
class BAWANGShampooFactory implements ShampooFactory {
@Override
public Liquid productionLiquid() {
return new BAWANGShampooLiquid();
}
@Override
public Box productionBox() {
return new BAWANGShampooBox();
}
@Override
public Shampoo getShampoo(Liquid liquid, Box box) {
return new BAWANGShampoo();
}
}
/**
* 清揚洗髮水工廠
*/
class ClearingShampooFactory implements ShampooFactory {
@Override
public Liquid productionLiquid() {
return new ClearShampooLiquid();
}
@Override
public Box productionBox() {
return new ClearingShampooBox();
}
@Override
public Shampoo getShampoo(Liquid liquid, Box box) {
return new ClearShampoo();
}
}
/**
* @ClassName : abstractFactory 抽象工廠
* @Description : 抽象工廠
*/
public class abstractFactory {
public static void main(String[] args) {
// 生產一瓶海飛絲的洗髮水
// 建立一個海飛絲的工廠
HearingShampooFactory hearingShampooFactory = new HearingShampooFactory();
// 生產海飛絲洗髮水液體
Liquid liquid = hearingShampooFactory.productionLiquid();
// 生產海飛絲的包裝
Box box = hearingShampooFactory.productionBox();
if (box instanceof HeadShouldersShampooBox && liquid instanceof HeadShouldersShampooLiquid) {
Shampoo shampoo = hearingShampooFactory.getShampoo(liquid, box);
if (shampoo instanceof HeadShouldersShampoo) {
System.out.println("生產海飛絲洗髮水成功");
}
}
// 生產一瓶霸王的洗髮水
// 建立一個霸王的工廠
BAWANGShampooFactory bawangShampooFactory = new BAWANGShampooFactory();
// 生產霸王洗髮水液體
Liquid liquid1 = bawangShampooFactory.productionLiquid();
// 生產霸王的包裝
Box box1 = bawangShampooFactory.productionBox();
if (liquid1 instanceof BAWANGShampooLiquid && box1 instanceof BAWANGShampooBox) {
Shampoo shampoo = bawangShampooFactory.getShampoo(liquid1, box1);
if (shampoo instanceof BAWANGShampoo) {
System.out.println("生產霸王洗髮水成功");
}
}
// 生產一瓶清揚洗髮水
// 建立一個清揚洗髮水工廠
ClearingShampooFactory clearingShampooFactory = new ClearingShampooFactory();
// 生產清揚洗髮水液體
Liquid liquid2 = clearingShampooFactory.productionLiquid();
// 生產清揚洗髮水瓶子
Box box2 = clearingShampooFactory.productionBox();
if (liquid2 instanceof ClearShampooLiquid && box2 instanceof ClearingShampooBox) {
Shampoo shampoo = clearingShampooFactory.getShampoo(liquid2, box2);
if (shampoo instanceof ClearShampoo) {
System.out.println("生產清揚洗髮水成功");
}
}
}
}
工廠設計模式,差不多就這些了。
本作品採用《CC 協議》,轉載必須註明作者和本文連結