上一篇:反射實例化對象 | 帶你學《Java語言高級特性》之八十二
【本節目標】
通過案例逐步掌握工廠設計模式,通過工廠類獲取指定接口的實例化對象。
反射與工廠設計模式
如果要想進行對象的實例化處理,除了可以使用關鍵字new之外,還可以使用反射機制來完成,於是此時一定會思考一個問題:為什麼要提供有一個反射的實例化?那麼到底是使用關鍵字new,還是使用反射呢?
如果要想更好的理解此類問題,最好的解決方案就是通過工廠設計模式來解決。
工廠模式的最大特點:客戶端的程序類不直接牽扯到對象的實例化管理,只與接口發生關聯,通過工廠類獲取指定接口的實例化對象。
範例:傳統的工廠設計模式
interface IMessage{
public void send(); //消息發送
}
class NetMessage implements IMessage{
public void send() {
System.out.println("【網絡消息發送】www.mldn.cn");
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
IMessage msg = new NetMessage(); //如果直接實例化則一定會有耦合問題
}
}
在實際的開發中,接口的主要作用是為不同層提供有一個操作的標準。但是如果此時直接將一個子類設置為接口實例化操作,那麼一定會有耦合問題,所以使用了工廠設計模式來解決此問題。
範例:利用工廠設計模式解決
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
IMessage msg = Factory.getInstance("netmessage");
msg.send(); //【網絡消息發送】www.mldn.cn
}
}
interface IMessage{
void send(); //消息發送
}
class NetMessage implements IMessage{
public void send() {
System.out.println("【網絡消息發送】www.mldn.cn");
}
}
class Factory{
private Factory(){} //沒有產生實例化對象的意義,所以構造方法私有化
public static IMessage getInstance(String className){
if("netmessage".equalsIgnoreCase(className)){
return new NetMessage();
}
return null;
}
}
靜態工廠設計模式
此種工廠設計模式屬於靜態工廠設計模式,也就是說如果現在要追加一個子類,則意味著工廠類一定要做出修改,因為如果不追加判斷是無法獲取指定接口對象的。
範例:為IMessage追加一個子類
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
// IMessage msg = Factory.getInstance("netmessage");
// msg.send();//【網絡消息發送】www.mldn.cn
IMessage msg = Factory.getInstance("cloudmessage");
msg.send();//【雲消息發送】www.mldnjava.cn
}
}
interface IMessage{
void send(); //消息發送
}
class NetMessage implements IMessage{
@Override
public void send() {
System.out.println("【網絡消息發送】www.mldn.cn");
}
}
class CloudMessage implements IMessage{
@Override
public void send() {
System.out.println("【雲消息發送】www.mldnjava.cn");
}
}
class Factory{
private Factory(){}
public static IMessage getInstance(String className){
if("netmessage".equalsIgnoreCase(className)){
return new NetMessage();
}else if("cloudmessage".equalsIgnoreCase(className)){
return new CloudMessage();
}
return null;
}
}
工廠設計模式最有效的解決的是子類與客戶端的耦合問題,但是解決的核心思想是在於提供了一個工廠類作為過渡端,但是隨著項目的進行,IMessage接口有可能會擁有更多的子類,而且隨著時間的推移,子類產生的可能會越來越多,那麼此時就意味著,工廠類永遠都要進行修改,並且永無停止之日。
那麼這時候最好的解決方案就是不使用關鍵字new來完成,因為關鍵字在new在使用時,需要有一個明確的類存在。而newInstance()方法只需要有一個明確表示類名稱的字符串即可。
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
IMessage msg = Factory.getInstance("cn.mldn.demo.NetMessage");
msg.send(); //【網絡消息發送】www.mldn.cn
}
}
interface IMessage{
void send(); //消息發送
}
class NetMessage implements IMessage{
public void send() {
System.out.println("【網絡消息發送】www.mldn.cn");
}
}
class CloudMessage implements IMessage{
@Override
public void send() {
System.out.println("【雲消息發送】www.mldnjava.cn");
}
}
class Factory{
private Factory(){}
public static IMessage getInstance(String className){
IMessage instance = null;
try {
instance = (IMessage) Class.forName(className).getDeclaredConstructor().newInstance();
}catch (Exception e) {
e.printStackTrace();
}
return instance;
}
}
這時可以發現,利用反射機制實現的工廠設計模式,最大的優勢在於:對於接口子類的擴充將不再影響到工廠類的定義。
反射工廠設計模式
但現在依然需要進一步思考,因為在實際的項目開發過程中,有可能會存在有大量的接口,並且這些接口都可能需要通過工廠類實例化,所以此時的工廠設計模式不應該只為IMessage接口服務,應該為所有接口服務。
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
IMessage msg = Factory.getInstance("cn.mldn.demo.NetMessage",IMessage.class);
msg.send(); //【網絡消息發送】www.mldn.cn
IService service=Factory.getInstance("cn.mldn.demo.HouseService",IService.class);
service.service(); //【服務】為您的住宿提供服務。
}
}
class Factory{
private Factory(){}
/**
* 獲取接口實例化對象
* @param className 接口的子類
* @param clazz 描述的是一個接口的類型
* @return 如果子類存在則返回指定接口的實例化對象
*/
@SuppressWarnings("unchecked")
public static <T> T getInstance(String className,Class<T> clazz){
T instance=null;
try {
instance=(T) Class.forName(className).getDeclaredConstructor().newInstance();
}catch (Exception e) {
e.printStackTrace();
}
return instance;
}
}
interface IService{
void service();
}
class HouseService implements IService{
@Override
public void service() {
System.out.println("【服務】為您的住宿提供服務。");
}
}
interface IMessage{
void send();//消息發送
}
class NetMessage implements IMessage{
public void send() {
System.out.println("【網絡消息發送】www.mldn.cn");
}
}
class CloudMessage implements IMessage{
@Override
public void send() {
System.out.println("【雲消息發送】www.mldnjava.cn");
}
}
此時的工廠模式將不再受限於指定的接口,可以為所有的接口提供實例化服務,達到可重用性。
想學習更多的Java的課程嗎?從小白到大神,從入門到精通,更多精彩不容錯過!免費為您提供更多的學習資源。
本內容視頻來源於阿里雲大學