1. 工廠模式分類
工廠模式主要負(fù)責(zé)將大量有共同接口的類實例化蝗碎,可以動態(tài)的決定創(chuàng)建哪一個類,而不事先知道要實例化具體哪一個類蹭睡。
- 簡單工廠模式:靜態(tài)工廠模式
- 工廠模式:多態(tài)工廠模式或者虛擬構(gòu)造工廠模式
- 抽象工廠模式:又稱為工具箱模式
2. 簡單工廠模式
簡單工廠模式是類的創(chuàng)建模式衍菱,又稱為靜態(tài)工廠方法,是有一個工廠的對象決定創(chuàng)建哪一類具體的產(chǎn)品肩豁。
這里有一個水果類脊串,水果類下面有不同的子類實現(xiàn)
Fruit:
public interface Fruit {
/**
* 生長
*/
void grow();
/**
* 收獲
*/
void harvest();
/**
* 種植
*/
void plant();
}
Apple(其他以此類推,不再一一列出)
public class Apple implements Fruit{
/**
* 樹齡
*/
private int treeAge;
@Override
public void grow() {
log("Apple is growing.");
}
@Override
public void harvest() {
log("Apple has been harvested.");
}
@Override
public void plant() {
log("Apple has been planted.");
}
public static void log(String msg)
{
System.out.println(msg);
}
public int getTreeAge(){
return treeAge;
}
public void setTreeAge(int treeAge){
this.treeAge = treeAge;
}
}
最后創(chuàng)建一個園丁類清钥,通過傳入不同的水果屬性琼锋,判斷水果的類型進(jìn)行創(chuàng)建,這是典型的靜態(tài)工廠模式祟昭。
public class FruitGardener {
/**
* 靜態(tài)工廠方法
*
* @param args
*/
public static void main(String[] args) {
try{
Fruit fruit = FruitGardener.factory("apple");
fruit.harvest();
fruit = FruitGardener.factory("grape");
fruit.harvest();
fruit = FruitGardener.factory("strawberry");
fruit.harvest();
}catch (BadFruitException e){
e.printStackTrace();
}
}
public static Fruit factory(String fruit) throws BadFruitException {
switch (fruit) {
case "apple":
return new Apple();
case "strawberry":
return new Strawberry();
case "grape":
return new Grape();
default:
throw new BadFruitException("Bad fruit request");
}
}
}
總結(jié)一下缕坎,簡單工廠模式的結(jié)構(gòu)為:
3. 工廠模式
工廠模式又成為動態(tài)工廠模式,由于靜態(tài)工廠模式的缺點(diǎn)是篡悟,有新的類加入時需要修改工廠類代碼谜叹,不符合開閉原則,因此引入類動態(tài)工廠模式搬葬,使用多態(tài)的方式去創(chuàng)建荷腊,具體創(chuàng)建類的過程交給子類去做,工廠和產(chǎn)品之間是一種平級的等級結(jié)構(gòu)急凰。
工廠模式存在四個角色:抽象產(chǎn)品女仰、具體產(chǎn)品、構(gòu)造者抡锈、具體構(gòu)造者
這里采用一個簡單的例子去說明
抽象產(chǎn)品類:PenCore 鋼筆:顏色+書寫
public abstract class PenCore {
public String color;
public abstract void writeWord(String s);
}
具體產(chǎn)品類:黑色鋼筆:設(shè)置顏色+書寫文字
public class BlackPenCore extends PenCore{
public BlackPenCore(){
color = "black";
}
@Override
public void writeWord(String s) {
System.out.println("write with "+ color+ ": "+s);
}
}
構(gòu)造者:BallPen: 返回一個鋼筆對象
public abstract class BallPen {
BallPen(){
System.out.println("create the pen with the "+ getPenCore().color+".");
}
public abstract PenCore getPenCore();
}
具體構(gòu)造者:BlackBallPen:返回具體的鋼筆對象
public class BlackBallPen extends BallPen{
@Override
public PenCore getPenCore(){
return new BlackPenCore();
}
}
模式的具體使用
public class Application {
public static void main(String[] args) {
PenCore penCore;
BallPen ballPen = new BlueBallPen();
penCore = ballPen.getPenCore();
penCore.writeWord("你好");
ballPen = new RedBallPen();
penCore = ballPen.getPenCore();
penCore.writeWord("Hello");
ballPen = new BlackBallPen();
penCore = ballPen.getPenCore();
penCore.writeWord("ni hao!");
}
}
運(yùn)行結(jié)果:
create the pen with the blue.
write with blue: 你好
create the pen with the red.
write with red: Hello
create the pen with the black.
write with black: ni hao!
其實Java的集合框架也有采用這種設(shè)計模式:
綜上所述疾忍,工廠模式的結(jié)構(gòu)為:
4. 抽象工廠模式
抽象工廠模式是工廠模式中最具一般性的一種形態(tài),提供一個創(chuàng)建一系列或相互依賴對象的接口床三,而無須制定他們具體的類一罩。
它與工廠模式的最大區(qū)別是:工廠模式面對一個產(chǎn)品等級的結(jié)構(gòu),而抽象工廠模式面對多個產(chǎn)品等級結(jié)構(gòu)撇簿。
舉個例子擒抛,兩個抽象產(chǎn)品一個褲子一個上衣:
褲子抽象產(chǎn)品:
public interface Trousers {
int getWaistSize();
int getHeight();
String getName();
}
上衣抽象產(chǎn)品
public interface UpperClothes {
int getChestSize();
int getHeight();
String getName();
}
褲子分為西褲和牛仔褲推汽,這里只顯示西褲:
public class WesternTrousers implements Trousers{
private int waistSize;
private int height;
private String name;
public WesternTrousers(int waistSize, int height, String name) {
this.waistSize = waistSize;
this.height = height;
this.name = name;
}
@Override
public int getWaistSize() {
return waistSize;
}
@Override
public int getHeight() {
return height;
}
@Override
public String getName() {
return name;
}
}
上衣分為牛仔上衣和西裝,這里只寫西裝
public class WesternUpperClothes implements UpperClothes {
private int chestSize;
private int height;
private String name;
public WesternUpperClothes(int chestSize, int height, String name) {
this.chestSize = chestSize;
this.height = height;
this.name = name;
}
@Override
public int getChestSize() {
return chestSize;
}
@Override
public int getHeight() {
return height;
}
@Override
public String getName() {
return name;
}
}
此時創(chuàng)建抽象工廠歧沪,具有創(chuàng)建上衣和褲子的方法
public interface ClothesFactory {
UpperClothes createUpperClothes(int chestSize, int height);
Trousers createTrousers(int waitSize, int height);
}
具體工廠包括兩個歹撒,北京的西裝工廠和上海的牛仔工廠,這里列舉北京的西裝工廠
public class BeijingClothesFactory implements ClothesFactory{
@Override
public UpperClothes createUpperClothes(int chestSize, int height) {
return new WesternUpperClothes(chestSize, height, "北京牌西服上衣");
}
@Override
public Trousers createTrousers(int waitSize, int height) {
return new WesternTrousers(waitSize, height, "北京牌西服褲子");
}
}
最后設(shè)置服裝店诊胞,輸入人的信息暖夭,可以創(chuàng)建具體的服裝
public class Shop {
UpperClothes clothes;
Trousers trousers;
public void giveSuit(ClothesFactory factory, int chestSize, int waistSize, int height){
clothes = factory.createUpperClothes(chestSize, height);
trousers = factory.createTrousers(waistSize, height);
showMess();
}
private void showMess(){
System.out.println("<套裝信息>");
System.out.println(clothes.getName()+" ");
System.out.println("胸圍:"+ clothes.getChestSize());
System.out.println("身高:"+ clothes.getHeight());
System.out.println(trousers.getName()+" ");
System.out.println("腰圍:"+ trousers.getWaistSize());
System.out.println("身高:"+ trousers.getHeight());
}
}
最后,服裝店可以對衣服進(jìn)行定制
public class Application {
public static void main(String[] args) {
Shop shop = new Shop();
ClothesFactory factory = new BeijingClothesFactory();
shop.giveSuit(factory, 110, 82, 170);
factory = new ShanghaiClothesFactory();
shop.giveSuit(factory, 120, 88, 180);
}
}
打印結(jié)果如下:
<套裝信息>
北京牌西服上衣
胸圍:110
身高:170
北京牌西服褲子
腰圍:82
身高:170
總結(jié)抽象工廠的模式為:
因此抽象工廠模式適用于以下情況:
- 一個系統(tǒng)不應(yīng)當(dāng)依賴與產(chǎn)品類實力如何被創(chuàng)建撵孤、組合和表達(dá)的細(xì)節(jié)迈着;
- 這個系統(tǒng)中有多于一個的產(chǎn)品族,而系統(tǒng)只消費(fèi)其中某一族的產(chǎn)品邪码;
- 同屬于一個產(chǎn)品族的產(chǎn)品是一起使用的裕菠;
- 系統(tǒng)提供一個產(chǎn)品類的庫,所有產(chǎn)品以同樣的接口出現(xiàn)闭专,從而實現(xiàn)客戶端不依賴于實現(xiàn)奴潘。
5. 源碼參考
由于篇幅原因,只顯示了一個子類影钉,完整的系統(tǒng)調(diào)用請參考鏈接画髓。