工廠,顧名思義在於對相關產品的批量添加,在開發中指將對象創建交給某個類,使得開發者不需要在意對象的創建。舉個例子,小青我的麪包店即將開業了。
/**
*
* @author 小青
* @Time 下午12:30:34
* @Function:小青的麪包店
*
*/
public class First {
public static void main(String[] args) {
System.out.println("小青的麪包店開業了");
System.out.println("小青製作了一組黑麪包");
System.out.println("小青製作了一組蜂蜜燕麥麪包");
System.out.println("小青製作了一組白麪包");
}
}
運行結果:
小青我發現,如果我還要製作其他類型的麪包呢?客戶端的代碼就會越來越龐大,而且改起來很是麻煩,經過一定的思考,我設計瞭如下操作
/**
*
* @author ricardo
* @Time 下午12:36:33
* @Function:麪包師小青
*
*/
public class BreadMaker {
public static void GetBread(int breadType) {
switch (breadType) {
case 1:
System.out.println("小青製作了一組黑麪包");
break;
case 2:
System.out.println("小青製作了一組蜂蜜燕麥麪包");
break;
case 3:
System.out.println("小青製作了一組白麪包");
break;
default:
System.out.println("小青製作了一組新的麪包");
break;
}
}
}
/**
*
* @author ricardo
* @Time 下午12:37:02
* @Function:小青的麪包店
*
*/
public class Second {
public static void main(String[] args) {
System.out.println("小青的麪包店開業了");
System.out.println("顧客想要黑麪包");
BreadMaker.GetBread(1);
System.out.println("顧客想要蜂蜜燕麥麪包");
BreadMaker.GetBread(2);
System.out.println("顧客想要白麪包");
BreadMaker.GetBread(3);
}
}
運行截圖:
這樣的過程看上去就合理多了,但是要修改麪包師類也是很麻煩的,所以我決定再次修改拆分
/**
*
* @author ricardo
* @Time 下午12:42:29
* @Function:麪包師
*
*/
public class BreadMaker {
public void GetBread() {
System.out.println("製作麪包");
}
}
/**
*
* @author ricardo
* @Time 下午12:45:19
* @Function:製作黑麪包
*
*/
public class BlackBread extends BreadMaker {
@Override
public void GetBread() {
System.out.println("製作一組黑麪包");
}
}
public class HoneyBread extends BreadMaker {
@Override
public void GetBread() {
System.out.println("製作一組蜂蜜燕麥麪包");
}
}
public class WhiteBread extends BreadMaker {
@Override
public void GetBread() {
System.out.println("製作一組白麪包");
}
}
將各種麪包都包裝成了BreadMaker的子類,重寫GetBread()方法,這樣在修改任何一種麪包的代碼都與其他麪包無關,同時還保證了麪包配方的安全性。
/**
*
* @author ricardo
* @Time 下午12:59:42
* @Function:簡單面包工廠類
*
*/
public class BreadFactory {
public static BreadMaker MakeBread(int breadType) {
BreadMaker breadMaker = null;
switch (breadType) {
case 1:
breadMaker = new BlackBread();
break;
case 2:
breadMaker = new HoneyBread();
break;
case 3:
breadMaker = new WhiteBread();
break;
default:
break;
}
return breadMaker;
}
}
public class Second {
public static void main(String[] args) {
BreadMaker breadMaker;
System.out.println("小青的麪包店開業了");
System.out.println("顧客要黑麪包");
breadMaker = BreadFactory.MakeBread(1);
breadMaker.GetBread();
System.out.println("顧客要白麪包");
breadMaker.GetBread();
breadMaker = BreadFactory.MakeBread(2);
System.out.println("顧客要蜂蜜燕麥麪包");
breadMaker = BreadFactory.MakeBread(3);
breadMaker.GetBread();
}
}
運行截圖:
以上採用的是簡單工廠模式,但是這樣做,在添加一種新麪包的時候,要修改工廠類,增加Case分支,對擴展開發的同時也對修改開放了,這讓小青我這個強迫症怎麼忍,於是,根據GOF對工廠方法的定義:定義一個創建對象的接口,讓子類決定實例化那一個類,工廠方法使一個類的實例化延遲到子類。再次對代碼進行修改
/**
*
* @author ricardo
* @Time 下午1:44:34
* @Function:工廠接口
*
*/
public interface IFactory {
BreadMaker CreateBread();
}
public class BlackBreadFactory implements IFactory {
@Override
public BreadMaker CreateBread() {
// TODO Auto-generated method stub
return new BlackBread();
}
}
public class HoneyBreadFactory implements IFactory {
@Override
public BreadMaker CreateBread() {
// TODO Auto-generated method stub
return new HoneyBread();
}
}
public class WhiteBreadFactory implements IFactory {
@Override
public BreadMaker CreateBread() {
// TODO Auto-generated method stub
return new WhiteBread();
}
}
客戶端實現對子類的實例化
public class Three {
public static void main(String[] args) {
BreadMaker breadMaker;
System.out.println("小青的麪包店開業了!");
System.out.println("顧客要買黑麪包");
IFactory breadFactory = new BlackBreadFactory();
breadMaker = breadFactory.CreateBread();
breadMaker.GetBread();
System.out.println("顧客要蜂蜜燕麥黑麪包");
breadFactory = new HoneyBreadFactory();
breadMaker = breadFactory.CreateBread();
breadMaker.GetBread();
System.out.println("顧客要買白麪包");
breadFactory = new WhiteBreadFactory();
breadMaker = breadFactory.CreateBread();
breadMaker.GetBread();
}
}
運行截圖:
這樣一來,新的代碼中增加新的麪包種類,只需要增加新麪包類和新的工廠方法接口實現就好了,具體的實例化哪個類的判斷放到了客戶端。
簡單工廠模式的最大優點是去除了客戶端與具體產品的依賴,雖然違背了開放-封閉原則,但是保持了封裝對象創建過程的優點。工廠方法模式在保留了簡單工廠模式優點的同時,也克服了其缺點,但對應的,每增加一個產品,都要添加一個產品工廠類,額外的增加了開發量。
以上內容,整理自劉徑舟,張玉華編著的《設計模式其實很簡單》讀書筆記,歡迎轉載.