工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
1. 為什么要有工廠模式?
"Talk is cheap,show me the code". 想要找到這個問題的答案,我們先來看看下面這個項目。
1.1 一個實體類
public class User{ public String username; public String password;
}
為了更方便講述,我盡量讓代碼精簡,方便我們深入了解想關注的點。
實體類很簡單,User對象,兩個成員變量,username 用戶名稱,password 用戶密碼
1.2 定義了一個IUser接口
也很簡單,只有一個insert方法
import com.xingyun.model.User; public interface IUser { void insert(User user); }
1.3 一個實現類IUserMySQLImpl.java
import com.xingyun.model.User;
import com.xingyun.myinterface.IUser; public class IUserMySQLImpl implements IUser{ @Override public void insert(User user) { // TODO Auto-generated method stub System.out.println("insert to MySQL"+user.toString()); } }
這個實現類實現了IUser接口,所以需要實現IUser接口定義的insert(User user)方法.
1.4 最后我們可能需要再多個地方調用
Test1.java
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; import com.xingyun.myinterface.impl.IUserMySQLImpl; public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=new IUserMySQLImpl(); test.insert(user); } }
Test2.java
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; import com.xingyun.myinterface.impl.IUserMySQLImpl; public class Test2 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=new IUserMySQLImpl(); test.insert(user); } }
我們可以發現Test1.java 和Test2.java 中調用方式都是這樣:
IUser test=new IUserMySQLImpl(); test.insert(user);
但是假設后來項目中MySQL不想用了,想換Oracle 數據庫了怎么辦?
1.6 我們需要新寫一個實現類 IUserOracleImpl.java
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; public class IUserOracleImpl implements IUser{ @Override public void insert(User user) { // TODO Auto-generated method stub System.out.println("insert to Oracle"+user.toString()); } }
1.7 這很正常,但是我們之前有多處調用,所以我們將不得不修改Test1.java 和Test2.java,
Test1.java
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; import com.xingyun.myinterface.impl.IUserOracleImpl; public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=new IUserOracleImpl(); test.insert(user); } }
Test2.java
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; import com.xingyun.myinterface.impl.IUserOracleImpl; public class Test2 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=new IUserOracleImpl(); test.insert(user); } }
試想下,假如Test1 ,Test 這類的調用方式有十幾處的話,那么這么多地方都要改,我們是不是要累死?
那么如何優化呢?
2. 工廠模式手動實現方式
聰明的大牛做了這樣的優化
2.1 實體類不變
public class User{ public String username; public String password; }
2.2 消息接口不變
import com.xingyun.model.User; public interface IUser { void insert(User user); }
2.3 一個實現類IUserMySQLImpl.java
import com.xingyun.model.User;
import com.xingyun.myinterface.IUser; public class IUserMySQLImpl implements IUser{ @Override public void insert(User user) { // TODO Auto-generated method stub System.out.println("insert to MySQL"+user.toString()); } }
2.4 實現類 IUserOracleImpl.java 不變
import com.xingyun.model.User; import com.xingyun.myinterface.IUser; public class IUserOracleImpl implements IUser{ @Override public void insert(User user) { // TODO Auto-generated method stub System.out.println("insert to Oracle"+user.toString()); } }
2.5 新建了一個這樣的類 IUserFactory.java
import com.xingyun.myinterface.IUser;
import com.xingyun.myinterface.impl.IUserMySQLImpl; public class IUserFactory { public static IUser getIUserImpl() { return new IUserMySQLImpl(); } }
2.6 最開始調用方式改變下
Test1.java
import com.xingyun.factory.IUserFactory; import com.xingyun.model.User; import com.xingyun.myinterface.IUser; public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=IUserFactory.getIUserImpl(); test.insert(user); } }
Test2.java
import com.xingyun.factory.IUserFactory; import com.xingyun.model.User; import com.xingyun.myinterface.IUser; public class Test2 { public static void main(String[] args) { // TODO Auto-generated method stub User user=new User(); user.username="admin"; user.password="root"; IUser test=IUserFactory.getIUserImpl(); test.insert(user); } }
然后將Test1.java和Test2.java 中原來的調用方式
IUser test=new IUserMySQLImpl();
test.insert(user);
改成了這樣:
IUser test=IUserFactory.getIUserImpl();
test.insert(user);
於是乎,我當需要將IUserMySQLImpl更換為IUserOracleImpl 的時候,我們只需要修改這個IUserFactory即可,Test1.java和Test2.java 任何調用的地方都不再需要改變。
import com.xingyun.myinterface.IUser; import com.xingyun.myinterface.impl.IUserOracleImpl; public class IUserFactory { public static IUser getIUserImpl() { return new IUserOracleImpl(); } }
你猜的沒錯,這就是Java 設計模式中著名的工廠模式,通過抽象出一個工廠,來屏蔽調用選擇哪一種實現類的,這個問題丟給工廠類來處理切換哪一個實現類。
2. 工廠模式Spring IOC實現方式
Mark:https://www.cnblogs.com/cowboys/p/6638484.html
待續。。。