一個考試系統,當考生的成績經過後(成績大於60分)會經過各類方式通知用戶。java
/** * 成績對象 */ public class Score { //成績 private int score; //是否使用app消息通知,使用0表示否,1表示是。下同 private int sendAPPMsg; //是否使用短信通知 private int sendSms; //是否使用郵件通知 private int sendMail; //是否使用站內消息通知 private int siteMsg; //其餘的一些非主要屬性再也不此加入,好比手機號,郵箱號等 //get and set method }
/** * 使用常規的if-else操做 */ public class IfDemo { /** * 使用if-else進行通知 * * @param score 傳入的分數對象 */ public void sendNotice(Score score) { if (score.getScore() >= 60) { if (score.getSendAPPMsg() == 1) { //這裏是進行通知的具體實現,爲了和後邊造成更直接的對比,我加了好多代碼 System.out.println("進行app消息推送1"); System.out.println("進行app消息推送2"); System.out.println("進行app消息推送3"); System.out.println("進行app消息推送4"); } if (score.getSendSms() == 1) { System.out.println("進行短信通知1"); System.out.println("進行短信通知2"); System.out.println("進行短信通知3"); System.out.println("進行短信通知4"); } if (score.getSendMail() == 1) { System.out.println("進行郵件通知1"); System.out.println("進行郵件通知2"); System.out.println("進行郵件通知3"); System.out.println("進行郵件通知4"); } if (score.getSiteMsg() == 1) { System.out.println("進行站內消息通知1"); System.out.println("進行站內消息通知2"); System.out.println("進行站內消息通知3"); System.out.println("進行站內消息通知4"); } } } }
對於每種通知方法,我只進行了一句簡單的打印,實際中就會寫上進行通知的方法算法
public class NoticeTest { private Score score; @BeforeEach public void beforeTest(){ score = new Score(); score.setScore(95); score.setSendAPPMsg(1); score.setSendMail(1); score.setSendSms(1); score.setSiteMsg(1); } @Test public void ifDemoTest() { IfDemo ifDemo = new IfDemo(); ifDemo.sendNotice(score); } }
這樣寫沒有任何問題,代碼確定是能跑起來的。可是,咱們是直掛將每一個通知的方法(也就是每種通知方法的具體實現)寫在了上邊代碼中,若是要改的話咱們就要對這裏進行修改。因此咱們進行一次優化,就是將上邊的每一種通知代碼進行一次方法抽取。設計模式
將上邊的各個通知方法進行一次抽取,能夠放在本類下,也能夠將通知方法單獨放在一個類中,我是放在了一個單獨的類中。通知類有以下方法:微信
/** * 通知類, */ public class NoticeService { public void sendAppNotice(){ System.out.println("進行app推送通知1"); System.out.println("進行app推送通知2"); System.out.println("進行app推送通知3"); System.out.println("進行app推送通知4"); } public void sendSms(){ System.out.println("進行短信通知1"); System.out.println("進行短信通知2"); System.out.println("進行短信通知3"); System.out.println("進行短信通知4"); } public void sendMail(){ System.out.println("進行郵件通知1"); System.out.println("進行郵件通知2"); System.out.println("進行郵件通知3"); System.out.println("進行郵件通知4"); } public void sendSiteMsg(){ System.out.println("進行站內消息通知1"); System.out.println("進行站內消息通知2"); System.out.println("進行站內消息通知3"); System.out.println("進行站內消息通知4"); } }
package cn.lyn4ever.v2; import cn.lyn4ever.bean.Score; /** * 進行分數判斷是否通知的類 */ public class NoticeDemo { /** * 處理是否進行通知的主要方法 * * @param score */ public void sendNotice(Score score) { NoticeService noticeService = new NoticeService(); if (score.getScore() >= 60) { if (score.getSendAPPMsg() == 1) { //這裏只須要寫這一句就能夠進行通知,而不像剛纔那樣,下同 noticeService.sendAppNotice(); } if (score.getSendSms() == 1) { noticeService.sendSms(); } if (score.getSendMail() == 1) { noticeService.sendMail(); } if (score.getSiteMsg() == 1) { noticeService.sendSiteMsg(); } } } }
@Test public void noticeDemoTest(){ NoticeDemo noticeDemo = new NoticeDemo(); noticeDemo.sendNotice(score); }
有小夥伴會問了,這樣寫的方法和上邊沒有任何區別啊?爲何要這麼作?app
這種方式雖然將通知方法進行了單獨的方法抽取,下降了必定的耦合。可是呢?ide
若是,咱們有一個或多個新的通知方式要添加,好比微信、QQ。那你要改的地方是哪兒?學習
1.在Score的bean中添加兩個字段,這個是必須的測試
2.在NoticeService中添加兩個新的通知方法優化
public void sendQQ(){ System.out.println("進行QQ消息通知1"); System.out.println("進行QQ消息通知2"); System.out.println("進行QQ消息通知3"); System.out.println("進行QQ消息通知4"); } public void sendWX(){ System.out.println("進行WX消息通知1"); System.out.println("進行WX消息通知2"); System.out.println("進行WX消息通知3"); System.out.println("進行WX消息通知4"); }
3.在NoticeDemo中添加兩個if判斷設計
if (score.getSendQQ() == 1) { noticeService.sendQQ(); } if (score.getSendWX() == 1) { noticeService.sendWX(); }
策略模式(Strategy),定義了一組算法,將每一個算法都封裝起來,而且使它們之間能夠互換
package cn.lyn4ever.v3; public interface INotice { void notice(); }
public class AppNoticeImpl implements INotice { @Override public void notice() { System.out.println("進行app消息推送"); } }
public class NoticeService3 { /** * 只提供一個通知方法,參數爲通知接口 * @param iNotice */ public void notice(INotice iNotice) { iNotice.notice(); } }
public class NoticeDemo3 { public void sendNotice(Score score) { NoticeService3 noticeService = new NoticeService3(); if (score.getScore() >= 60) { if (score.getSendAPPMsg() == 1) { noticeService.notice(new AppNoticeImpl()); } if (score.getSendSms() == 1) { noticeService.notice(new SmsNoticeImpl()); } if (score.getSendMail() == 1) { noticeService.notice(new MailNoticeImpl()); } if (score.getSiteMsg() == 1) { noticeService.notice(new SiteNoticeImpl()); } } } }
有的小夥伴可能會認爲這不是在重複造輪子嗎?這和方法1、方法二讓人更難理解
其實並非在重複地造輪子,這樣作就體現了面向對象開發的「封裝」特性,相比第一種方法,更好地「面向對象」開發,並且封裝了整個每個通知方法的實現,下降了通知這個功能的耦合度,使得每一種通知方法有本身的實現。
好比上邊的一個新須要,當咱們須要新增「QQ」和「微信」通知的時候,這時只須要添加兩個新的INotice的實現類,並在if條件中加兩句就能夠了,NoticeService類不用再次修改
更多的設計模式學習,請關注個人微信公衆號「小魚與Java」