先上一段代碼:java
public class HelloWorldTest { public static void main(String[] args) { System.out.println("Hello world!"); } }
這是Java裏面最簡單的一段代碼了,作的事情很是簡單:控制檯打印出「Hello world!」字符串。很明顯,這段代碼很很差拓展,假如咱們想打印別的內容呢?ide
OK,接下來作一點簡單的改動:函數
public class HelloWorldTest { public static void main(String[] args) { if (args.length > 0) { System.out.println(args[0]); } else { System.out.println("Hello world!"); } } }
這樣當咱們運行帶參數時,控制檯會輸出咱們的第一個參數。這樣咱們就取得了第一個小小的進步:咱們能夠不修改代碼就控制了不一樣的輸出。但還有問題,這個類既控制了參數的輸入,又控制了參數的輸出。換句話說就是:消息的輸入和輸出是耦合在一塊兒的。this
讓咱們更進一步。首先咱們添加一個獲取消息的類:spa
public class MessageConsumer { public String sayHello(String message) { if (Objects.isNull(message) || message.length() < 1) { return "Hello world!"; } return message; } }
這樣當輸入的參數不爲null或者空字符串時,輸出參數,不然輸出Hello world!。調用方只須要在調用的時候傳入不一樣的參數,就達到了輸出不一樣內容的目的。OK,如今已經解耦了消息的輸出方,但生產方還在main方法裏。接下來解耦消息的生產方。添加一個新的類來生產消息:code
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; } }
這樣主函數只須要new出MessageRenderer和MessageConsumer對象便可,對於消息怎麼生產和消費則不須要關心。但這樣的問題是MessageRender和MessageConsumer耦合在一塊兒。對象
咱們更進一步對兩個類進行抽象:blog
public interface MessageConsumer { String sayHello(String message); }
public interface MessageRenderer { void render(); MessageConsumer getMessageConsumer(); void setMessageConsumer(MessageConsumer messageConsumer); }
新建實現類:接口
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(); } }
至此,消息的生產和消費解耦開來,生產方只依賴消費方的抽象而不是具體實現,主程序只負責new出須要的生產方和消費方便可。三者的關係如如:
運行程序咱們能夠獲得咱們想要的輸出內容,但還有一點小問題:咱們如今要的是HelloWorldMessageConsumer,假如咱們須要別的MessageConsumer呢?那就須要改主程序代碼了。
下面咱們添加一個類來生產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(); } }
這樣,當咱們須要不一樣的MessageRenderer或MessageConsumer時,只須要在配置文件裏指定不一樣的對象便可。實際上,到這裏已經完成了一個簡易版的IOC實現。
這部分只須要添加配置便可,略。