有兩個實現了Message接口的類News和Email.
interface Message {
public void print(String str);
}
class Email implements Message {
@Override
public void print(String str) {
System.out.println("郵件內容" + str);
}
}
class News implements Message {
@Override
public void print(String str) {
System.out.println("新聞內容" + str);
}
}
如果我們總是通過new的方式來創建接口對象,那我們每次都要在代碼里修改new的對象,這樣耦合度比較大,而且容易錯,我們希望可以通過其他方式而不是修改代碼的方式來創建不同的對象。 最早的解耦合的方式是利用工廠類,這個可以利用反射來完成。
利用反射來做,首先就是獲取類對象。這個有三種方法。可以看上一篇文章。
取得類對象之后,可以用Class里的newInstance()來實例化對象。
newInstance() 就是調用類的無參構造。
我們首先創建一個工廠類。
class factory {
public static Message getInstance(String str) {
try {
return (Message) Class.forName(str).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
這個工廠類通過傳入的類名稱,直接返回該類的實例化對象。
public class TestDemo {
public static void main(String[] args) throws Exception{
Message mes = factory.getInstance("cn.mldn.demo.News");
mes.print("今天是五月四號");
}
}
調用factory的getInstance方法,創建相應的實例化對象。
運行得到:news 內容今天是五月四號
這個方法,在main方法里,依然要明確地寫出要操作的類的名稱,這可以繼續優化。最好的設計方案永遠不是點對點直達,我們要解耦合。這個時候可以利用屬性文件。在java.util中有一個Properties類,它是Hashtable的子類。
Properties 里的 load 和stroe兩個方法。
load:通過輸入流讀取屬性內容
stroe:通過輸出流來輸出屬性內容
public class TestProperities {
public static void main(String[] args) throws Exception {
Properties pro = new Properties();
pro.setProperty("Message.classname", "cn.mldn.demo.News"); //設置鍵值對
pro.setProperty("city", "beijing");
pro.store(new FileOutputStream(new File("D:"+File.separator + "info.properties")), "This is Message File"); //存儲
}
}
通過setProperty()來設置key和value的對應。運行之后,能在D盤找到文件info.properties。其中的內容為:
#This is Message File
#Thu Apr 06 09:04:08 CST 2017
Message.classname=cn.mldn.demo.News
city=beijing
其中內容就是key = value
讀取Properties的方法:
public static void main(String[] args) throws Exception {
Properties pro = new Properties();
pro.load(new FileInputStream(new File("D:"+File.separator +"info.properties")));
System.out.println(pro.getProperty("city"));
}
我們通過load()函數,按簡單的面向行的格式從輸入字符流中讀取屬性列表(鍵和元素對)。但是這個還是要精確地給出文件所在的位置,這個可以利用ResourceBundle來優化。
public static void main(String[] args) throws Exception {
Properties pro = new Properties();
ResourceBundle rb = ResourceBundle.getBundle("info");
System.out.println(rb.getString("city"));
}
我們一般是把這個文件和其他源代碼一起放在src文件夾里面,然后用ResourceBundle,rb就能自動從工作目錄下找到Info這個資源包。然后通過rb.getString()就可以獲取關鍵字對應的值。(這個真是方便,不用寫一大串文件的地址)
然后我們可以直接修改properties中的鍵值對來修改要生成的對象。要修改的時候直接修改配置文件中關鍵字對應的值就可以了。
public static void main(String[] args) throws Exception{
Properties pro = new Properties();
ResourceBundle rb = ResourceBundle.getBundle("info");
Message mes = factory.getInstance(rb.getString("Message.classname"));
mes.print("今天是五月四號");
}
運行結果為:
eMail 內容今天是五月四號