在項(xiàng)目的開(kāi)發(fā)中,我們很難做到開(kāi)發(fā)一套標(biāo)準(zhǔn)的流程來(lái)解決所有客戶的需求。比如,我們當(dāng)前的計(jì)量項(xiàng)目,分別運(yùn)行于赤峰市和河北省。雖然兩個(gè)區(qū)域處理的業(yè)務(wù)相同,但是對(duì)細(xì)節(jié)的實(shí)現(xiàn)要求卻不同。前面也學(xué)習(xí)過(guò)計(jì)量檢定軟件,其為了解決各個(gè)定制者使用的功能需求,最后采取的方案是:將基礎(chǔ)項(xiàng)目復(fù)制多份,進(jìn)而滿足不同的客戶需求。優(yōu)點(diǎn)當(dāng)然是有的,但比起缺點(diǎn)來(lái),優(yōu)點(diǎn)便不值一提。缺點(diǎn)很明顯,總結(jié)為一句話就是:項(xiàng)目變得難以維護(hù)。所以,當(dāng)前讓我們看到的就是,幾個(gè)開(kāi)發(fā)人員,每天處于解決問(wèn)題當(dāng)中。本文將給出一種方案,來(lái)有效的規(guī)避上述問(wèn)題。
資源與環(huán)境
示例代碼:https://github.com/mengyunzhi/springbootsamplecode/tree/master/dynamic-autowire
開(kāi)發(fā)環(huán)境:java1.8 + spring-boot:2.1.3.release
需求假設(shè)
- 假設(shè)使用本項(xiàng)目的人員為:中國(guó)人、美國(guó)人,分別能接受的語(yǔ)言為中文和英文。
-
項(xiàng)目運(yùn)行后,可以根據(jù)當(dāng)前的訪問(wèn)人員是國(guó)籍來(lái)動(dòng)態(tài)顯示:
你好
或hello
-
有新的需求后,比如:增加德國(guó)人并顯示
hallo
。增加功能時(shí),不更改核心代碼。 - 不使用if else
注意:如果你看完需求假設(shè)后,毫無(wú)觸動(dòng),請(qǐng)忽略本文以下內(nèi)容
解決方案
解決方案中,我們涉及了兩種設(shè)計(jì)模塊,分別為:策略模式
及工廠模式
。
策略模式:一般用于將具體的算法
進(jìn)行抽象及剝離。此項(xiàng)目中,我們的具體算法是說(shuō)你好
。
工廠模式:一般用于根據(jù)環(huán)境來(lái)動(dòng)態(tài)的創(chuàng)建bean的情況下。引項(xiàng)目中,我們將根據(jù)不同國(guó)家的人,來(lái)返回不同的說(shuō)你好
這個(gè)算法。
先給出uml圖:
speakservice
speakservice
即為我們供其它模塊調(diào)用的說(shuō)話服務(wù)
,調(diào)用其中的sayhello()
來(lái)完成說(shuō)你好
功能。
1
2
3
4
5
6
7
8
|
package com.mengyunzhi.demo.dynamicautowire; /** * 你好 */ public interface speakservice { void sayhello(); } |
在其實(shí)現(xiàn)類中,我們注入sayhellofactory
,讓其來(lái)返回正確的sayhelloservice
,最終調(diào)用sayhello()
來(lái)完成目標(biāo)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.service; /** * 你好 */ @service public class speakserviceimpl implements speakservice { private final sayhellofactory sayhellofactory; // 說(shuō)話工廠 @autowired public speakserviceimpl(sayhellofactory sayhellofactory) { this .sayhellofactory = sayhellofactory; } @override public void sayhello() { this .sayhellofactory.getsayhelloservice().sayhello(); } } |
sayhellofactory
1
2
3
4
5
6
7
8
9
10
11
|
package com.mengyunzhi.demo.dynamicautowire; /** * 說(shuō)話工廠 */ public interface sayhellofactory { void setcountrycode(countrycode countrycode); sayhelloservice getsayhelloservice(); } |
在此,我們?cè)黾右粋€(gè)countrycode
表示當(dāng)前訪問(wèn)者的國(guó)家。其實(shí)在獲取訪問(wèn)者國(guó)家時(shí),我們也可以調(diào)用其它bean的其它來(lái)實(shí)現(xiàn)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.mengyunzhi.demo.dynamicautowire; /** * 國(guó)家代碼 */ public enum countrycode { china(( byte ) 0 , "中國(guó)" ), usa(( byte ) 1 , "美國(guó)" ); private byte code; private string name; countrycode( byte code, string name) { this .code = code; this .name = name; } public byte getcode() { return code; } public string getname() { return name; } } |
使用enum
來(lái)控制范圍,避免factory
在獲取bean時(shí)發(fā)生異常。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.service; import java.util.hashmap; import java.util.list; import java.util.map; /** * 說(shuō)話工廠 */ @service public class sayhellofactoryimpl implements sayhellofactory { /** * bean列表 */ private final map< byte , sayhelloservice> servicesbycode = new hashmap<>(); /** * 國(guó)家代碼 */ private countrycode countrycode = countrycode.china; @override public void setcountrycode(countrycode countrycode) { this .countrycode = countrycode; } /** * 初始化 * * @param sayhelloservices spring獲取到的所以實(shí)現(xiàn)了speakservice的bean */ @autowired public void init(list<sayhelloservice> sayhelloservices) { for (sayhelloservice sayhelloservice : sayhelloservices) { this .register(sayhelloservice.getcode(), sayhelloservice); } } /** * 注冊(cè)bean * * @param code 代碼 * @param sayhelloservice bean */ private void register( byte code, sayhelloservice sayhelloservice) { this .servicesbycode.put(code, sayhelloservice); } /** * 獲取bean * * @return 對(duì)應(yīng)的sayhelloservice bean */ @override public sayhelloservice getsayhelloservice() { return this .servicesbycode.get( this .countrycode.getcode()); } } |
增加map<byte, sayhelloservice> servicesbycode
來(lái)存儲(chǔ)對(duì)應(yīng)國(guó)家的sayhelloservice
bean。增加getsayhelloservice()
來(lái)根據(jù)當(dāng)前國(guó)家代碼來(lái)返回相應(yīng)的bean。
sayhelloservice
1
2
3
4
5
6
7
8
9
10
|
package com.mengyunzhi.demo.dynamicautowire; /** * 說(shuō)話 */ public interface sayhelloservice { void sayhello(); byte getcode(); } |
將sayhello()
方法抽離,getcode()
以獲取國(guó)家代碼。
中國(guó)人你好
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.stereotype.component; /** * 中國(guó)話 */ @component public class sayhelloservicechineseimpl implements sayhelloservice { @override public void sayhello() { system.out.println( "您好" ); } @override public byte getcode() { return countrycode.china.getcode(); } } |
美國(guó)人hello
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.stereotype.component; /** * 美國(guó)話 */ @component public class sayhelloserviceenglishimpl implements sayhelloservice { @override public void sayhello() { system.out.println( "hello" ); } @override public byte getcode() { return countrycode.usa.getcode(); } } |
測(cè)試
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package com.mengyunzhi.demo.dynamicautowire; import org.junit.test; import org.junit.runner.runwith; import org.springframework.beans.factory.annotation.autowired; import org.springframework.boot.test.context.springboottest; import org.springframework.test.context.junit4.springrunner; @springboottest @runwith (springrunner. class ) public class speakserviceimpltest { @autowired speakservice speakservice; @autowired sayhellofactory sayhellofactory; @test public void sayhello() { // 默認(rèn)說(shuō)你好 speakservice.sayhello(); // 將國(guó)家設(shè)置為美國(guó),再說(shuō)你好 sayhellofactory.setcountrycode(countrycode.usa); speakservice.sayhello(); // 將國(guó)家設(shè)置為中國(guó),再說(shuō)你好 sayhellofactory.setcountrycode(countrycode.china); speakservice.sayhello(); } } |
您好
hello
您好
時(shí)序圖
增加德國(guó)人
增加德國(guó)人sayhelloservicegermanyimpl
.
在countrycode
中,增加德國(guó).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.stereotype.component; @component public class sayhelloservicegermanyimpl implements sayhelloservice { @override public void sayhello() { system.out.println( "hallo" ); } @override public byte getcode() { return countrycode.germany.getcode(); } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package com.mengyunzhi.demo.dynamicautowire; /** * 國(guó)家代碼 */ public enum countrycode { china(( byte ) 0 , "中國(guó)" ), usa(( byte ) 1 , "美國(guó)" ), germany(( byte ) 2 , "德國(guó)" ); private byte code; private string name; countrycode( byte code, string name) { this .code = code; this .name = name; } public byte getcode() { return code; } public string getname() { return name; } } |
單元測(cè)試
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@test public void sayhello1() { // 默認(rèn)說(shuō)你好 speakservice.sayhello(); // 將國(guó)家設(shè)置為美國(guó),再說(shuō)你好 sayhellofactory.setcountrycode(countrycode.usa); speakservice.sayhello(); // 將國(guó)家設(shè)置為德國(guó),再說(shuō)你好 sayhellofactory.setcountrycode(countrycode.germany); speakservice.sayhello(); // 將國(guó)家設(shè)置為中國(guó),再說(shuō)你好 sayhellofactory.setcountrycode(countrycode.china); speakservice.sayhello(); } |
測(cè)試結(jié)果如下:
您好
hello
hallo
您好
總結(jié)
在解決問(wèn)題時(shí),只所有我們看的不夠遠(yuǎn),可能是由于自己站的不夠高。同樣的問(wèn)題,困惑我了多日,直到近期系統(tǒng)的學(xué)習(xí)設(shè)計(jì)模式
、angular官方教程
、spring 實(shí)戰(zhàn)
后,結(jié)合近期項(xiàng)目變更帶來(lái)的新需求,才在使用設(shè)計(jì)模式解決此問(wèn)題上有所啟發(fā)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://segmentfault.com/a/1190000018673552