反射與工廠設計模式

菜鳥的傳奇人生發表於2020-12-12

一、什麼是反射

Java是先編譯再執行的語言,而反射可以讓我們在程式執行時動態載入類並獲取類的詳細資訊,本質是JVM得到java.lang.Class物件之後,再對class物件進行反編譯,從而獲取物件的各種資訊

二、獲取Class物件的三種方式

(1)Object裡的getClass方法獲取
在這裡插入圖片描述
(2)每個資料型別(包括基本的資料型別)都有一個靜態的class屬性
在這裡插入圖片描述
(3)通過class類的靜態方法forName
在這裡插入圖片描述

三、根據class物件反射例項化物件

利用class.getDeclaredConstructor().newInstance()方法獲取物件
在這裡插入圖片描述

四、一般的工廠模式設計方法

一個介面----若干實現了該介面的類—一個工廠類(工廠類建構函式私有化,給出一個靜態的獲取例項物件的方法)

interface IMessage {
    public void send();
}
class NetMessage implements IMessage {

    @Override
    public void send() {
        System.out.println("我是netMessage");
    }
}
class ServiceMessage implements IMessage {

    @Override
    public void send() {
        System.out.println("我是serviceMessage");
    }
}
class Factory {
    private Factory(){}
    public static IMessage getInstance(String className){
        if("netMessage".equals(className)){
            return new NetMessage();
        }else{
            return new ServiceMessage();
        }
    }
}
public class Test {
    public static void main(String[] args) {
        IMessage iMessage = Factory.getInstance("netMessage");
        iMessage.send();
    }
}

這段程式碼存在的一個很嚴重的問題在於,當IMessage的子類增多時,工廠類又得加上判斷,隨著子類的增加,工廠類越來越複雜

五、使用反射改進後的工廠設計模式

interface IMessage {
    public void send();
}
class NetMessage implements IMessage {

    @Override
    public void send() {
        System.out.println("我是netMessage");
    }
}
class ServiceMessage implements IMessage {

    @Override
    public void send() {
        System.out.println("我是serviceMessage");
    }
}
class Factory {
    private Factory(){}
    public static IMessage getInstance(String className){
        try{
            return (IMessage) Class.forName(className).getDeclaredConstructor().newInstance(); 
        }catch(Exception e){
            e.printStackTrace();
        }
        
    }
}
public class Test {
    public static void main(String[] args) {
        IMessage iMessage = Factory.getInstance("NetMessage");
        iMessage.send();
    }
}

現在又有了一個新的問題,當一個工廠類需要同時對多個介面進行物件的例項化時,怎麼做?

六、使用泛型實現工廠多介面的例項化

class Factory {
    private Factory(){}
    public static <T> T getInstance(String className){
        try{
            return (T) Class.forName(className).getDeclaredConstructor().newInstance();
        }catch(Exception e){
            e.printStackTrace();
        }

    }
}

相關文章