設(shè)計(jì)模式的起源
模式的研究起源于建筑設(shè)計(jì)大師Christopher Alexander的關(guān)于城市規(guī)劃和建筑設(shè)計(jì)的著作卸察。盡管他的著作是針對城市規(guī)劃和建筑設(shè)計(jì)的铅祸,但是作者的觀點(diǎn)實(shí)際上適用于所有工程設(shè)計(jì)領(lǐng)域,包括軟件開發(fā)設(shè)計(jì)領(lǐng)域洪乍。
Alexander 在他的著作中指出夜焦,「每一個(gè)模式描述了一個(gè)在我們周圍不斷重復(fù)發(fā)生的問題岂贩,以及該問題的解決方案的核心萎津。這樣,你就能一次又一次地使用該方案而不必做重復(fù)勞動(dòng)」锉屈。盡管Alexander所指的是城市和建筑模式,但他的思想也同樣適用于面向?qū)ο笤O(shè)計(jì)模式遂黍,只是在面向?qū)ο蟮慕鉀Q方案里,我們用對象和接口代替了墻壁和門窗铃彰。兩類模式的核心都在于提供了相關(guān)問題的解決方案芯咧。
創(chuàng)建模式-為什么使用簡單工廠模式
設(shè)計(jì)模式一般主要分為創(chuàng)建模式、結(jié)構(gòu)模式邪铲、行為模式无拗。本文主要講解「創(chuàng)建模式」中的「簡單工廠模式」。
創(chuàng)建模式(Creational Pattern)是對類的實(shí)例化過程的抽象化蓝纲。一些系統(tǒng)在創(chuàng)建對象時(shí)税迷,需要?jiǎng)討B(tài)地決定怎樣創(chuàng)建對象,創(chuàng)建哪些對象箭养,以及如何組合和表示這些對象毕泌。創(chuàng)建模式描述了怎樣構(gòu)造和封裝這些動(dòng)態(tài)的決定。
創(chuàng)建模式分為類的創(chuàng)建模式和對象的創(chuàng)建模式兩種撼泛。
1.類的創(chuàng)建模式:類的創(chuàng)建模式使用繼承關(guān)系愿题,把類的創(chuàng)建延遲到子類,從而封裝了客戶端將得到哪些具體類的信息潘酗,并且隱藏了這些類的實(shí)例是如何創(chuàng)建和放在一起。
2.對象的創(chuàng)建模式: 對象的創(chuàng)建模式則把對象的創(chuàng)建過程動(dòng)態(tài)地委派給另一個(gè)對象琐脏,從而動(dòng)態(tài)地決定客戶端將得到哪些具體類的實(shí)例,以及這些類的實(shí)例是如何被創(chuàng)建和組合在一起的吹艇。
創(chuàng)建模式包括:簡單工廠模式阅签、工廠方法模式、抽象工廠模式路克、單例模式养交、多例模式、建造模式灰羽、原始模型模式等等鱼辙。
工廠模式的幾種形態(tài)
工廠模式專門負(fù)責(zé)將大量有共同接口的類實(shí)例化。工廠模式可以動(dòng)態(tài)決定將哪一個(gè)類實(shí)例化怠噪,不必事先知道每次要實(shí)例化哪一個(gè)類杜跷。工廠模式有以下幾種形態(tài):
1.簡單工廠模式(Simple Factory Pattern)
2.工廠方法模式(Factory Method Pattern)
3.抽象工廠模式(Abstract Factory Pattern)
簡單工廠模式,或稱靜態(tài)工廠方法(Static Factory Method)模式憋槐。該模式的核心是工廠類,這個(gè)類含有必要的判斷邏輯淑趾,可以決定在什么時(shí)候創(chuàng)建哪一個(gè)產(chǎn)品類的實(shí)例。而客戶端則可以免除直接創(chuàng)建產(chǎn)品對象的責(zé)任驳概,而僅僅負(fù)責(zé)「消費(fèi)」產(chǎn)品旷赖。簡單工廠模式通過這種做法實(shí)現(xiàn)了對責(zé)任的分割更卒。
栗子:
比如說有一家農(nóng)場,向市場銷售各種類型的水果俯萌。在農(nóng)場中有種植以下水果:
1.蘋果 Apple
2.葡萄 Grape
3.草莓 Strawberry
水果與其他的植物有很大的不同,水果最終是可以采摘食用的弱恒。那么一個(gè)自然的作法就是建立一個(gè)各種水果都適用的接口棋恼,以便與農(nóng)場里的其他植物區(qū)分開。

水果接口規(guī)定出所有的水果必須實(shí)現(xiàn)的接口义起,包括任何水果類必須具備的方法:
1.種植plant()
2.生長grow()
3.收獲harvest()
水果接口源碼:
public interface Fruit {
//種植
void plant();
//生長
void grow();
//收獲
void harvest();
}
Apple類是水果類的一種师崎,因此它實(shí)現(xiàn)了水果接口所聲明的所有方法。另外齐蔽,由于蘋果是多年生植物床估,因此多出一個(gè)treeAge性質(zhì),描述蘋果樹的樹齡蛙吏。
蘋果類的源碼:
public class Apple implements Fruit {
private int treeAge;
public void plant() {
System.out.println(“Apple has been planted.”);
}
public void grow() {
System.out.println(“Apple is growing.”);
}
public void harvest() {
System.out.println(“Apple has been harvested.”);
}
public int getTreeAge() {
return treeAge;
}
public void setTreeAge(int treeAge) {
this.treeAge = treeAge;
}
}
同樣鞋吉,Grape類是水果類的一種,也實(shí)現(xiàn)了Fruit接口所聲明的所有方法泼诱。但由于葡萄分為有籽和無籽兩種赊锚,因此,比普通水果多出一個(gè)seedless性質(zhì)耸袜。
葡萄類的源碼:
public class Grape implements Fruit {
private boolean seedless;
public void plant() {
System.out.println(“Grape has been planted.”);
}
public void grow() {
System.out.println(“Grape is growing.”);
}
public void harvest() {
System.out.println(“Grape has been harvested.”);
}
public boolean getSeedless() {
return seedless;
}
public void setSeedless(boolean seedless) {
this.seedless = seedless;
}
}
Strawberry 類實(shí)現(xiàn)了Fruit接口堤框,因此也是水果類型的子類型。
草莓類源碼:
public class Strawberry implements Fruit {
public void plant() {
System.out.println(“Grape has been planted.”);
}
public void grow() {
System.out.println(“Grape is growing.”);
}
public void harvest() {
System.out.println(“Grape has been harvested.”);
}
}
接下來启绰,我們需要定義一個(gè)工廠類沟使,在我們的栗子中是FruitFactory類。該類中有一個(gè)靜態(tài)的getFruit方法着倾,取決于條件的給予叽唱,返回不同的Fruit實(shí)例。
class FruitFactory {
public static Fruit getFruit(String criteria) {
if (criteria.equals(“Apple”)) {
return new Apple();
} else if (criteria.equals(“Grape")) {
return new Grape();
} else if (criteria.equals(“Strawberry”)) {
return new Strawberry();
}
return null;
}
}
最后作為消費(fèi)者虎眨,僅需調(diào)用FruitFactory的靜態(tài)方法getFruit()镶摘,即可以得到可口的水果了。具體代碼如下:
public class FruitConsumer {
public static void main(String[] args) {
Fruit fruit = null;
fruit = FruitFactory.getFruit("Apple");
fruit.harvest();
fruit = FruitFactory.getFruit("Grape");
fruit.harvest();
fruit = FruitFactory.getFruit("Strawberry");
fruit.harvest();
}
}
輸出結(jié)果:
Apple has been harvested.
Grape has been harvested.
Strawberry has been harvested.
參考:
「1」Design Patterns: Elements of Reusable Object-Oriented Software
「2」Java 與模式
「3」A Java Factory Pattern example