摘要:但還有問(wèn)題,這個(gè)類(lèi)既控制了參數(shù)的輸入,又控制了參數(shù)的輸出。換句話(huà)說(shuō)就是消息的輸入和輸出是耦合在一起的。進(jìn)一步解耦讓我們更進(jìn)一步。接下來(lái)解耦消息的生產(chǎn)方。實(shí)際上,到這里已經(jīng)完成了一個(gè)簡(jiǎn)易版的實(shí)現(xiàn)。
從Hello world開(kāi)始
先上一段代碼:
public class HelloWorldTest { public static void main(String[] args) { System.out.println("Hello world!"); } }
這是Java里面最簡(jiǎn)單的一段代碼了,做的事情非常簡(jiǎn)單:控制臺(tái)打印出“Hello world!”字符串。很明顯,這段代碼很不好拓展,假如我們想打印別的內(nèi)容呢?
第一步改動(dòng)OK,接下來(lái)做一點(diǎn)簡(jiǎn)單的改動(dòng):
public class HelloWorldTest { public static void main(String[] args) { if (args.length > 0) { System.out.println(args[0]); } else { System.out.println("Hello world!"); } } }
這樣當(dāng)我們運(yùn)行帶參數(shù)時(shí),控制臺(tái)會(huì)輸出我們的第一個(gè)參數(shù)。這樣我們就取得了第一個(gè)小小的進(jìn)步:我們可以不修改代碼就控制了不同的輸出。但還有問(wèn)題,這個(gè)類(lèi)既控制了參數(shù)的輸入,又控制了參數(shù)的輸出。換句話(huà)說(shuō)就是:消息的輸入和輸出是耦合在一起的。
進(jìn)一步解耦讓我們更進(jìn)一步。首先我們添加一個(gè)獲取消息的類(lèi):
public class MessageConsumer { public String sayHello(String message) { if (Objects.isNull(message) || message.length() < 1) { return "Hello world!"; } return message; } }
這樣當(dāng)輸入的參數(shù)不為null或者空字符串時(shí),輸出參數(shù),否則輸出Hello world!。調(diào)用方只需要在調(diào)用的時(shí)候傳入不同的參數(shù),就達(dá)到了輸出不同內(nèi)容的目的。OK,現(xiàn)在已經(jīng)解耦了消息的輸出方,但生產(chǎn)方還在main方法里。接下來(lái)解耦消息的生產(chǎn)方。添加一個(gè)新的類(lèi)來(lái)生產(chǎn)消息:
public class MessageRenderer { private MessageConsumer messageConsumer; public void render(){ if (Objects.isNull(messageConsumer)){ System.out.println("Hello world!"); }else { System.out.println(messageConsumer.sayHello("MessageRenderer")); } } public MessageConsumer getMessageConsumer() { return messageConsumer; } public void setMessageConsumer(MessageConsumer messageConsumer) { this.messageConsumer = messageConsumer; } }
這樣主函數(shù)只需要new出MessageRenderer和MessageConsumer對(duì)象即可,對(duì)于消息怎么生產(chǎn)和消費(fèi)則不需要關(guān)心。但這樣的問(wèn)題是MessageRender和MessageConsumer耦合在一起。
面向接口我們更進(jìn)一步對(duì)兩個(gè)類(lèi)進(jìn)行抽象:
public interface MessageConsumer { String sayHello(String message); }
public interface MessageRenderer { void render(); MessageConsumer getMessageConsumer(); void setMessageConsumer(MessageConsumer messageConsumer); }
新建實(shí)現(xiàn)類(lèi):
public class HelloWorldMessageConsumer implements MessageConsumer { @Override public String sayHello(String message) { return message; } }
public class HelloWorldMessageRenderer implements MessageRenderer { private MessageConsumer messageConsumer; @Override public void render() { if (Objects.isNull(messageConsumer)) { System.out.println("Hello world!"); } else { System.out.println(messageConsumer.sayHello("HelloWorldMessageRenderer")); } } @Override public MessageConsumer getMessageConsumer() { return messageConsumer; } @Override public void setMessageConsumer(MessageConsumer messageConsumer) { this.messageConsumer = messageConsumer; } }
程序入口:
public class HelloWorldTest { public static void main(String[] args) { MessageRenderer renderer = new HelloWorldMessageRenderer(); MessageConsumer consumer = new HelloWorldMessageConsumer(); renderer.setMessageConsumer(consumer); renderer.render(); } }
至此,消息的生產(chǎn)和消費(fèi)解耦開(kāi)來(lái),生產(chǎn)方只依賴(lài)消費(fèi)方的抽象而不是具體實(shí)現(xiàn),主程序只負(fù)責(zé)new出需要的生產(chǎn)方和消費(fèi)方即可。三者的關(guān)系如如:
運(yùn)行程序我們可以得到我們想要的輸出內(nèi)容,但還有一點(diǎn)小問(wèn)題:我們現(xiàn)在要的是HelloWorldMessageConsumer,假如我們需要?jiǎng)e的MessageConsumer呢?那就需要改主程序代碼了。
簡(jiǎn)易版IOC下面我們添加一個(gè)類(lèi)來(lái)生產(chǎn)MessageConsumer和MessageRenderer:
public class MessageSupportFactory { private static MessageSupportFactory instance; private Properties properties; private MessageRenderer messageRenderer; private MessageConsumer messageConsumer; static { instance = new MessageSupportFactory(); } public static MessageSupportFactory getInstance() { return instance; } private MessageSupportFactory() { properties = new Properties(); try { properties.load(this.getClass().getResourceAsStream("/msf.properties")); String rendererClass = properties.getProperty("renderer.class"); String consumerClass = properties.getProperty("consumer.class"); messageRenderer = (MessageRenderer) Class.forName(rendererClass).newInstance(); messageConsumer = (MessageConsumer) Class.forName(consumerClass).newInstance(); } catch (Exception e) { e.printStackTrace(); } } public MessageRenderer getMessageRenderer() { return messageRenderer; } public MessageConsumer getMessageConsumer() { return messageConsumer; } }
msg.properties代碼如下:
renderer.class=org.chunrun.learn.sp.message.HelloWorldMessageRenderer consumer.class=org.chunrun.learn.sp.message.HelloWorldMessageConsumer
主程序代碼如下:
public class HelloWorldTest { public static void main(String[] args) { MessageConsumer consumer = MessageSupportFactory.getInstance().getMessageConsumer(); MessageRenderer renderer = MessageSupportFactory.getInstance().getMessageRenderer(); renderer.setMessageConsumer(consumer); renderer.render(); } }
這樣,當(dāng)我們需要不同的MessageRenderer或MessageConsumer時(shí),只需要在配置文件里指定不同的對(duì)象即可。實(shí)際上,到這里已經(jīng)完成了一個(gè)簡(jiǎn)易版的IOC實(shí)現(xiàn)。
使用Spring重構(gòu)這部分只需要添加配置即可,略。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/69273.html
摘要:框架最初是由編寫(xiě)的,并且年月首次在許可下發(fā)布。在一個(gè)方法執(zhí)行之后,只有在方法退出拋出異常時(shí),才能執(zhí)行通知在建議方法調(diào)用之前和之后,執(zhí)行通知。方法執(zhí)行之后,不考慮其結(jié)果,執(zhí)行通知。 導(dǎo)讀: 在上篇文章的結(jié)尾提到了Spring Boot 提供了一系列的框架整合(Starter POMs)幫助我們提升開(kāi)發(fā)效率,但是這并不意味著我們不需要學(xué)習(xí)這些框架,反而更需要去學(xué)習(xí),通過(guò)學(xué)習(xí)這些框架可以使...
摘要:簡(jiǎn)介為了寫(xiě)容器源碼分析系列的文章,我特地寫(xiě)了一篇容器的導(dǎo)讀文章。在做完必要的準(zhǔn)備工作后,從本文開(kāi)始,正式開(kāi)始進(jìn)入源碼分析的階段。從緩存中獲取單例。返回以上就是和兩個(gè)方法的分析。 1. 簡(jiǎn)介 為了寫(xiě) Spring IOC 容器源碼分析系列的文章,我特地寫(xiě)了一篇 Spring IOC 容器的導(dǎo)讀文章。在導(dǎo)讀一文中,我介紹了 Spring 的一些特性以及閱讀 Spring 源碼的一些建議。在...
摘要:今天來(lái)學(xué)習(xí)一包導(dǎo)入在官網(wǎng)下載開(kāi)發(fā)包然后導(dǎo)入需要的包到項(xiàng)目目錄下。 今天來(lái)學(xué)習(xí)Spring ioc . 一、spring jar 包導(dǎo)入 在 spring 官網(wǎng)下載開(kāi)發(fā)包 spring-framework-4.2.4.RELEASE,然后導(dǎo)入需要的 jar 包到項(xiàng)目 /lib/ 目錄下。 ?showImg(https://segmentfault.com/img/bVbbiyW?w=34...
摘要:本文是容器源碼分析系列文章的第一篇文章,將會(huì)著重介紹的一些使用方法和特性,為后續(xù)的源碼分析文章做鋪墊。我們可以通過(guò)這兩個(gè)別名獲取到這個(gè)實(shí)例,比如下面的測(cè)試代碼測(cè)試結(jié)果如下本小節(jié),我們來(lái)了解一下這個(gè)特性。 1. 簡(jiǎn)介 Spring 是一個(gè)輕量級(jí)的企業(yè)級(jí)應(yīng)用開(kāi)發(fā)框架,于 2004 年由 Rod Johnson 發(fā)布了 1.0 版本。經(jīng)過(guò)十幾年的迭代,現(xiàn)在的 Spring 框架已經(jīng)非常成熟了...
摘要:從使用到原理學(xué)習(xí)線(xiàn)程池關(guān)于線(xiàn)程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實(shí)現(xiàn)在軟件開(kāi)發(fā)中,分散于應(yīng)用中多出的功能被稱(chēng)為橫切關(guān)注點(diǎn)如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計(jì)模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過(guò)的點(diǎn)點(diǎn)滴滴,依然清楚的記得當(dāng)初愛(ài)情萌芽的模樣…… Java 進(jìn)階面試問(wèn)題列表 -...
閱讀 1480·2019-08-30 15:55
閱讀 1179·2019-08-30 15:52
閱讀 1302·2019-08-29 13:53
閱讀 1474·2019-08-29 11:19
閱讀 2980·2019-08-26 13:29
閱讀 538·2019-08-26 11:33
閱讀 2601·2019-08-23 17:20
閱讀 1032·2019-08-23 14:14