梳理
最近在重構一段代碼,發現之前的流程大概是如下圖,這樣的設計結構。
一、這是一個發送消息的流程,長長的一段代碼,通過依賴構成整個流程的架構。整個流程依賴三個環節:適配、發送、保存,其中發送又依賴消息體生成。
二、由於消息類型不同,適配、發送、保存的具體實現不同,所以代碼中大量的充斥着if ... else ...的判斷語句。
這不僅導致代碼可讀性很差,而且還產生了大量冗餘代碼。
重構
針對如上問題,首先是通過組合的方式重新封裝。
一、提取一個更高的抽象(Mesasge),這裏組合了Sender和Saver兩個行爲,這裏只組合行爲,不組合實現。
這樣的好處,是外觀代碼變得更加清晰,如下面代碼:
Message message = adapterService.adapter(jsonMessage); message.getSender().send(); message.getSaver().save();
之前和同事討論這裏,很形象的比如成,Sender像一張弓,Message像一支箭,getSender()可以獲取不同的弓,Message也可以是不同的箭,通過不同的實現隨意組合。
二、這裏以服務號消息(ServiceNoMessage)爲例,SamplerMessage是Message的一種具體實現,其中SamplerSender和SamplerSaver分別是Sender和Saver的具體實現。
通過組合的方式,就可以在不改變外觀行爲的框架下,構造針對不同特定的具體實現。
抽象封裝Message,以及組合Sender和Saver可以參見如下代碼:
public class SamplerMessage implements Message { private Sender sender; private Saver saver; private String jsonMessage; private MessageSenderService messageSenderService; private MessageBodyService messageBodyService; public SamplerMessage(String jsonMessage, MessageSenderService messageSenderService, MessageBodyService messageBodyService) { this.jsonMessage= jsonMessage; // 封裝service到Message this.messageSenderService = messageSenderService; this.messageBodyService= messageBodyService; } public Sender getSender() throws Exception { sender = new SamplerSender(jsonMessage, messageSenderService, messageBodyService); return sender; } public Saver getSaver() { saver = new SamplerSaver(jsonMessage); return saver; } }
優化
在重構中,提取一些共性的行爲和屬性,通過繼承,在子類封裝每個特性的行爲和屬性。
在實現MessageBodyService服務時,發現不同實現中,有着很多共性的一些,所以通過抽象類的方式,封裝共性的,在具體的實現中,封裝特性的。
以MessageBodyService爲例,不同的實現都會調用初始init()方法,但是generate()會有所不同,如下圖:
AbsMessageBodyService的抽象實現如下:
public abstract class AbsMessageBodyService implements MessageBodyService { public void init() throws Exception { ... generate(); ... } protected abstract void generate() throws Exception; }
ServiceNoMessageBodyServiceImpl的具體實現:
public class ServiceNoMessageBodyServiceImpl extends AbsMessageBodyService { protected String generate() throws Exception { ... } }
MessageBody的調用:
public class SamplerMessageBody implements MessageBody { private MessageBodyService messageBodyService; public SamplerMessageBody() throws Exception { this.messageBodyService= new ServiceNoMessageBodyServiceImpl(); initMessageBody(); } private void initMessageBody() throws Exception { messageBodyService.init(); } }
—————————— 本文同步發佈於 ZHANGSR 我的個人博客 ——————————