老闆:阿飛啊,我們公司最近接了個項目,你看着設計一下,我給你說下需求。
項目組長阿飛:好啊,什麼需求?
老闆:我們找了一個合作的商鋪,他們要設計一套麪包銷售系統。主要功能,根據用戶選擇的麪包種類來下訂單,麪包目前有奶油口味麪包和蘋果口味麪包,所有面包的製作流程都是---攪拌,搓圓,加工,烘烤。
項目組長阿飛:好的,我去想想怎麼設計。
項目組長阿飛:小三啊,我給你個任務,…………,聽懂了嗎?
阿三:聽懂了,飛哥。
項目組長阿飛:嗯嗯,好的,這個任務就交給你了,我要去處理點事情,我相信你。
阿三:。。。
三天過後。
阿三:飛哥,設計好了,你看下。
1package com.factoryPattern.breadKind.factory;
2
3/**
4 * @program: designPattern
5 * @description: 麪包口味的抽象類
6 * @author: Mr.Yang
7 * @create: 2018-11-18 19:24
8 **/
9public abstract class BreadFactory {
10 protected String name;
11 protected String type;
12
13 public BreadFactory stir(){
14 System.out.println("攪拌");
15 return this;
16 }
17
18 public BreadFactory rubbingRound(){
19 System.out.println("搓圓");
20 return this;
21 }
22
23 public BreadFactory machining(){
24 System.out.println("加工");
25 return this;
26 }
27 public BreadFactory bake(){
28 System.out.println("烘烤");
29 return this;
30 }
31
32 public String getName() {
33 return name;
34 }
35
36 public BreadFactory setName(String name) {
37 this.name = name;
38 return this;
39 }
40
41 public String getType() {
42 return type;
43 }
44
45 public BreadFactory setType(String type) {
46 this.type = type;
47 return this;
48 }
49}
現在已有的兩種口味繼承這個抽象類--奶油麪包
1package com.factoryPattern.breadKind;
2
3import com.factoryPattern.breadKind.factory.BreadFactory;
4
5/**
6 * @program: designPattern
7 * @description: 奶油味麪包
8 * @author: Mr.Yang
9 * @create: 2018-11-18 19:24
10 **/
11public class CreamBread extends BreadFactory {
12 public CreamBread(){
13 name="奶油味";
14 type="2";
15 }
16 //可以重寫父類方法,進行特殊處理
17}
蘋果味麪包
1package com.factoryPattern.breadKind;
2
3import com.factoryPattern.breadKind.factory.BreadFactory;
4
5/**
6 * @program: designPattern
7 * @description: 蘋果味麪包
8 * @author: Mr.Yang
9 * @create: 2018-11-18 19:25
10 **/
11public class AppleBread extends BreadFactory {
12 public AppleBread(){
13 name="蘋果味";
14 type="1";
15 }
16 //可以重寫父類方法,進行特殊處理
17}
然後是銷售系統
1package com.factoryPattern.breadKind.breadOrder;
2
3import com.factoryPattern.breadKind.AppleBread;
4import com.factoryPattern.breadKind.CreamBread;
5import com.factoryPattern.breadKind.factory.BreadFactory;
6
7/**
8 * @program: designPattern
9 * @description: 麪包訂單銷售類
10 * @author: Mr.Yang
11 * @create: 2018-11-18 19:26
12 **/
13public class BreadOrder {
14
15
16 BreadFactory orderBread(String type){
17 BreadFactory breadFactory;
18 if("cream".equalsIgnoreCase(type)){
19 System.out.println("創建奶油口味麪包");
20 breadFactory=new CreamBread();
21 }else if("apple".equalsIgnoreCase(type)){
22 System.out.println("創建蘋果口味麪包");
23 breadFactory=new AppleBread();
24 }else{
25 System.out.println("無法確認的麪包類型");
26 return null;
27 }
28
29 return breadFactory.stir()
30 .rubbingRound()
31 .machining()
32 .bake();
33 }
34}
項目組長阿飛:三啊,不錯,學會使用抽象了,但是如果我還要增加好幾種麪包類型呢?阿爾法麪包銷售不好,不想做這個了呢?之前給你說過設計模式的原則之一,對拓展開放,對修改關閉。如果有改動,可能會一直在這個代碼的基礎上累加做修改的。最好把創建對象的代碼與銷售的代碼分隔開。
阿三:好的,我再修改修改(真的是,搞這麼麻煩幹嘛!)
又三天過後。
阿三:飛哥,修改好了,你看下。
新增了一個工程類
1package com.factoryPattern.breadCreate;
2
3import com.factoryPattern.breadKind.AppleBread;
4import com.factoryPattern.breadKind.CreamBread;
5import com.factoryPattern.breadKind.factory.BreadFactory;
6
7/**
8 * @program: designPattern
9 * @description: 麪包創建工程
10 * @author: Mr.Yang
11 * @create: 2018-11-18 19:37
12 **/
13public class BreadCreateFactory {
14 public BreadFactory createBread(String type){
15 BreadFactory breadFactory=null;
16 if("cream".equalsIgnoreCase(type)){
17 System.out.println("創建奶油口味麪包");
18 breadFactory=new CreamBread();
19 }else if("apple".equalsIgnoreCase(type)){
20 System.out.println("創建蘋果口味麪包");
21 breadFactory=new AppleBread();
22 }else{
23 System.out.println("無法確認的麪包類型");
24 return null;
25 }
26 return breadFactory;
27 }
28}
修改了銷售類
1package com.factoryPattern.breadKind.breadOrder;
2
3import com.factoryPattern.breadCreate.BreadCreateFactory;
4import com.factoryPattern.breadKind.factory.BreadFactory;
5
6/**
7 * @program: designPattern
8 * @description: 麪包訂單銷售類
9 * @author: Mr.Yang
10 * @create: 2018-11-18 19:26
11 **/
12public class BreadOrder {
13 BreadCreateFactory breadCreateFactory;
14
15 public BreadOrder(BreadCreateFactory breadCreateFactory) {
16 this.breadCreateFactory = breadCreateFactory;
17 }
18
19 BreadFactory orderBread(String type) {
20 return breadCreateFactory.createBread(type)
21 .stir()
22 .rubbingRound()
23 .machining()
24 .bake();
25 }
26}
項目組長阿飛:不錯,這是一個簡單工廠,但是你要記住,這並不是一個設計模式,而是一個編程習慣,一個不錯的編程習慣,簡單工廠把全部的事情,在一個地方處理完了,工廠方法是創建一個框架,讓子類決定如何實現。還有領導說需求變了,這個麪包店開了分店,一個在泰國,一個在新加坡,你看着再修改下吧,你可以考慮加入工廠方法。
阿三:好的(我服了,真的是****)
又三天過後。
阿三:飛哥,修改好了,這是完整代碼,你看下。
先是一個麪包商店抽象類
1package com.factoryPattern.breadStore;
2
3import com.factoryPattern.factory.BreadFactory;
4
5/**
6 * @program: designPattern
7 * @description: 麪包商店抽象類
8 * @author: Mr.Yang
9 * @create: 2018-11-18 19:51
10 **/
11public abstract class BreadStoreFactory {
12
13 public BreadFactory orderBread(String type) {
14 return createBread(type)
15 .stir()
16 .rubbingRound()
17 .machining()
18 .bake();
19 }
20
21 abstract BreadFactory createBread(String type);
22}
創建一箇中國店鋪子類實現商店抽象類
1package com.factoryPattern.breadStore;
2
3import com.factoryPattern.factory.BreadFactory;
4import com.factoryPattern.kind.ChinaAppleBread;
5import com.factoryPattern.kind.ChinaCreamBread;
6
7/**
8 * @program: designPattern
9 * @description: 中國店鋪子類
10 * @author: Mr.Yang
11 * @create: 2018-11-18 19:55
12 **/
13public class ChinaStore extends BreadStoreFactory{
14 @Override
15 BreadFactory createBread(String type) {
16 BreadFactory breadFactory=null;
17 if("cream".equalsIgnoreCase(type)){
18 System.out.println("創建中國奶油口味麪包");
19 breadFactory=new ChinaCreamBread();
20 }else if("apple".equalsIgnoreCase(type)){
21 System.out.println("創建中國蘋果口味麪包");
22 breadFactory=new ChinaAppleBread();
23 }else{
24 System.out.println("無法確認的麪包類型");
25 return null;
26 }
27 return breadFactory;
28 }
29}
創建一個新加坡店鋪子類
1package com.factoryPattern.breadStore;
2
3import com.factoryPattern.factory.BreadFactory;
4import com.factoryPattern.kind.SingaporeAppleBread;
5import com.factoryPattern.kind.SingaporeCreamBread;
6
7/**
8 * @program: designPattern
9 * @description: 新加坡店鋪子類
10 * @author: Mr.Yang
11 * @create: 2018-11-18 19:56
12 **/
13public class SingaporeStore extends BreadStoreFactory {
14 @Override
15 BreadFactory createBread(String type) {
16 BreadFactory breadFactory=null;
17 if("cream".equalsIgnoreCase(type)){
18 System.out.println("創建新加坡奶油口味麪包");
19 breadFactory=new SingaporeCreamBread();
20 }else if("apple".equalsIgnoreCase(type)){
21 System.out.println("創建新加坡蘋果口味麪包");
22 breadFactory=new SingaporeAppleBread();
23 }else{
24 System.out.println("無法確認的麪包類型");
25 return null;
26 }
27 return breadFactory;
28 }
29}
創建一個泰國店鋪子類
1package com.factoryPattern.breadStore;
2
3import com.factoryPattern.factory.BreadFactory;
4import com.factoryPattern.kind.ThailandAppleBread;
5
6/**
7 * @program: designPattern
8 * @description: 泰國店鋪子類
9 * @author: Mr.Yang
10 * @create: 2018-11-18 19:56
11 **/
12public class ThailandStore extends BreadStoreFactory {
13 @Override
14 BreadFactory createBread(String type) {
15 BreadFactory breadFactory=null;
16 if("cream".equalsIgnoreCase(type)){
17 System.out.println("創建泰國奶油口味麪包");
18 breadFactory=new ThailandAppleBread();
19 }else if("apple".equalsIgnoreCase(type)){
20 System.out.println("創建泰國蘋果口味麪包");
21 breadFactory=new ThailandAppleBread();
22 }else{
23 System.out.println("無法確認的麪包類型");
24 return null;
25 }
26 return breadFactory;
27 }
28}
麪包口味的抽象類
1package com.factoryPattern.factory;
2
3/**
4 * @program: designPattern
5 * @description: 麪包口味的抽象類
6 * @author: Mr.Yang
7 * @create: 2018-11-18 19:24
8 **/
9public abstract class BreadFactory {
10 protected String name;
11 protected String type;
12
13 public BreadFactory stir(){
14 System.out.println("攪拌");
15 return this;
16 }
17
18 public BreadFactory rubbingRound(){
19 System.out.println("搓圓");
20 return this;
21 }
22
23 public BreadFactory machining(){
24 System.out.println("加工");
25 return this;
26 }
27 public BreadFactory bake(){
28 System.out.println("烘烤");
29 return this;
30 }
31
32 public String getName() {
33 return name;
34 }
35
36 public BreadFactory setName(String name) {
37 this.name = name;
38 return this;
39 }
40
41 public String getType() {
42 return type;
43 }
44
45 public BreadFactory setType(String type) {
46 this.type = type;
47 return this;
48 }
49}
中國蘋果口味麪包
1package com.factoryPattern.kind;
2
3import com.factoryPattern.factory.BreadFactory;
4
5/**
6 * @program: designPattern
7 * @description: 中國蘋果口味麪包
8 * @author: Mr.Yang
9 * @create: 2018-11-18 19:48
10 **/
11public class ChinaAppleBread extends BreadFactory {
12 public ChinaAppleBread(){
13 name="中國蘋果口味";
14 type="1";
15 }
16 //可以重寫父類方法,進行特殊處理
17}
中國奶油口味麪包
1package com.factoryPattern.kind;
2
3import com.factoryPattern.factory.BreadFactory;
4
5/**
6 * @program: designPattern
7 * @description: 中國奶油口味麪包
8 * @author: Mr.Yang
9 * @create: 2018-11-18 19:48
10 **/
11public class ChinaCreamBread extends BreadFactory {
12 public ChinaCreamBread(){
13 name="中國奶油口味";
14 type="2";
15 }
16 //可以重寫父類方法,進行特殊處理
17}
還有新加坡蘋果口味麪包,新加坡奶油口味麪包,泰國蘋果口味麪包,泰國奶油口味麪包
測試類
1package com.factoryPattern.patternTest;
2
3import com.factoryPattern.breadStore.BreadStoreFactory;
4import com.factoryPattern.breadStore.ChinaStore;
5
6/**
7 * @program: designPattern
8 * @description: 測試類
9 * @author: Mr.Yang
10 * @create: 2018-11-18 20:13
11 **/
12public class Test {
13 public static void main(String[] args) {
14 System.out.println("中國顧客買蘋果味道麪包");
15 BreadStoreFactory chinaBreadStoreFactory = new ChinaStore();
16 chinaBreadStoreFactory.orderBread("apple");
17 }
18}
測試結果
1中國顧客買蘋果味道麪包
2創建中國蘋果口味麪包
3攪拌
4搓圓
5加工
6烘烤
項目組長阿飛:看着不錯,給我講解一下吧。
阿三:我所用的是設計模式中的工廠模式,讓子類決定該創建的對象是什麼,來達到將對象創建的過程封裝的目的。我簡單的畫了個圖
阿三:大致如圖,工程模式的定義:定義了一個創建對象的接口,但有子類決定要實例化的類是哪一個。工程方法讓類把實例化推遲到子類
項目組長阿飛:很好,看來你已經掌握了工程模式的精髓,工程模式遵循了一個設計原則:“要依賴抽象,不要依賴具體實現。”,它有一個響亮的名字:“依賴倒置原則”。 你看你這兩個圖。創建者抽象BreadStoreFactory依賴與BreadFactory抽象類,麪包的具體實現(chinaAppleBread,chinaCreamBread)依賴與BreadFactory抽象類,想要遵循依賴倒置原則,工程方法並非是唯一的,但是確是最有威力的技巧之一。
阿三:好的(我早就知道了---膨脹的一批)
JAVA知識分享總結
掃描二維碼關注微信公衆號!
Gatiln
掃描二維碼加我微信好友!
知識分享羣
掃描二維碼進微信交流羣!