標籤:object public java 程式 反射 原廠模式
1、反射 && Class類
假設有一個Test類定義如下:
class Test{public void testFunction(){System.out.println("you are here...");}}
這時,我們需要一個執行個體化的Test類型的對象,通常的做法是:
Test test1 = new Test();
通常這種做法是足夠的,但在某些特定的情境下,new很可能並不是最理想的執行個體化對象方式(見後文)
而反射機制,往往能彌補new在這些情境下的不足。
而反射的實現離不開一個重要的類:Class類。
Class類可以簡單理解為:“類的類”,至於具體是什麼類呢,這是需要程式在運行時推導的,因此Class類的泛型用 ? 表示一個未知的類。
Class<?>
下面有三種得到指定類的Class<?>類型對象的方式:
//方式1:通過Object類的getClass()方法取得(通常很少用這種方式)Test test_1 = new Test();Class<?> cls_1 = test_1.getClass();System.out.println(cls_1.getName());
//方式2:使用“類.class”取得Class<?> cls_2 = Test.class;System.out.println(cls_2.getName());
//方式3:使用Class中的forName方法 (常用方式) Class<?> cls_3 = Class.forName("com.test.mine.Test");System.out.println(cls_3.getName());
有了這個 Class<?>的對象,就可以調用其內部的 newInstance()方法,得到一個要求的對象了
接下來,執行個體化目標對象:
Test obj = (Test)cls_3.newInstance(); //這個函數的傳回值類型是Object
2、應用情境
有這樣一種情境:比如在原廠模式下,我們有可能需要經常增刪工廠生產的產品,在這樣的情境下,如果用new去實現工廠的生產方法,由於new必須調用指定類的構造方法的特性會讓程式的整體結構非常死板。
package com.test.mine;/////傳統的interface Fruit {public void eat() ;}class Apple implements Fruit {public void eat() {System.out.println("吃蘋果。");}}class Orange implements Fruit {public void eat() {System.out.println("吃橘子。");}}/////////////////////public class ClassFactory {public static Fruit getInstance(String className) {if("apple".equals(className)){return new Apple() ;}if("orange".equals(className)){return new Orange();}//////.......return null;}public static void main(String[] args) {Fruit apple = ClassFactory.getInstance("apple");apple.eat();Fruit orange = ClassFactory.getInstance("orange");orange.eat();}}
舉個例子:一旦生產的產品發生了改變,違背“低耦合”特性的傳統的原廠模式需要手動修改工廠的生產方法,而如果能讓工廠的生產方法去動態推導生產什麼產品,並生產對應的產品,那麼系統的耦合性就會提高許多。
具體的實現如下:
package com.test.mine;interface NewFruit {public void eat() ;}class NewApple implements NewFruit {public void eat() {System.out.println("吃蘋果。");}}class NewOrange implements NewFruit {public void eat() {System.out.println("吃橘子。");}}public class NewFactory {public static NewFruit getInstance(String className){NewFruit ret = null;try {ret = (NewFruit)Class.forName(className).newInstance();} catch (Exception e) {// TODO: handle exception}return ret;}//////public static void main(String[] args) {NewFruit apple = NewFactory.getInstance("com.test.mine.NewApple");apple.eat();NewFruit orange = NewFactory.getInstance("com.test.mine.NewOrange");orange.eat();}}
//有關原廠模式,之後會寫一篇文章,單獨介紹
3、反射方法
//反射方法Class<?> cls_4 = Class.forName("com.test.mine.Test");Method m1 = cls_4.getDeclaredMethod("testFunction");Object obj = cls_4.newInstance();m1.invoke(obj);
java中的反射機制