工厂模式及在项目中的应用
工廠模式分為簡單工廠、工廠方法模式和抽象工廠模式。簡單工廠顧名思義是最簡單的,從一個工廠獲取所需的產品類似于factory.getProduct1();或factory.getProduct2(),最經典的運用switch語句。簡單工廠要增加產品要修改源碼,破壞ocp原則(對擴展開放,修改封閉)
工廠方法模式與簡單工廠最不一樣的是工廠方法模式有工廠接口
抽象工廠模式與工廠方法模式最大的不同:工廠方法模式的產品都衍生于同一個接口或抽象類,而抽象工廠模式的產品衍生自不同的接口或抽象類。因為工廠方法模式針對一個產品等級結構,而抽象工廠方法針對多個,分別對應一個接口(抽象類)和多個接口(抽象類)。什么產品等級結構?舉個例子,比如車子,分奧迪和寶馬,而奧迪和寶馬分為大排量和小排量的,那么大排量的奧迪和小排量的奧迪屬于同一產品等級結構,而大排量的奧迪和大排量的寶馬屬于同一產品族。如果針對一個產品等級結構,也就是奧迪或寶馬,那么工廠產品為一個產品等級結構就使用工廠方法模式,如果針對多個,如寶馬和奧迪,那么就使用抽象工廠模式,它的產品是一個產品族。這就是它們的應用場景。
這里用一個例子熟悉一下抽象工廠模式。(使用單例模式避免大量工廠創建,浪費資源,不懂看前面有一篇說單例的)
public interface IFactoryDao {public IUserDao createUserDao();public IAddressDao createAddressDao(); }//工廠接口 public interface IAddressDao {public void add(Address address,int userId);public void update(Address address);public void delete(int id);}//產品1接口 public interface IUserDao {public void add(User user);public void delete(int id);public void update(User user);}//產品2接口 public class UserJDBCDao implements IUserDao {@Overridepublic void add(User user) {System.out.println("UserJDBCDao....add");}@Overridepublic void delete(int id) {System.out.println("UserJDBCDao....delete");}@Overridepublic void update(User user) {System.out.println("UserJDBCDao....update");}}//針對JDBC的產品2實現public class AddressJDBCDao implements IAddressDao {@Overridepublic void add(Address address, int userId) {System.out.println("addressJDBCDao....add");}@Overridepublic void update(Address address) {System.out.println("addressJDBCDao....update");}@Overridepublic void delete(int id) {System.out.println("addressJDBCDao....delete");}}//針對JDBC的產品1實現
public class JDBCDaoFactory implements IFactoryDao {private static JDBCDaoFactory factory = new JDBCDaoFactory();private JDBCDaoFactory(){}public static IFactoryDao getInstance() {return factory;}@Overridepublic IUserDao createUserDao() {return new UserJDBCDao();}@Overridepublic IAddressDao createAddressDao() {return new AddressJDBCDao();}}//工廠接口實現1(JDBC)
public class UserMySqlDao implements IUserDao {@Overridepublic void add(User user) {System.out.println("UserMySqlDao....add");}@Overridepublic void delete(int id) {System.out.println("UserMySQlDao....delete");}@Overridepublic void update(User user) {System.out.println("UserMySqlDao....update");}}//針對MySql的產品2實現
public class AddressMySqlDao implements IAddressDao {@Overridepublic void add(Address address, int userId) {System.out.println("addressMySqlDao....add");}@Overridepublic void update(Address address) {System.out.println("addressMySqlDao...update");}@Overridepublic void delete(int id) {System.out.println("addressMySqlDao....delete");}}//針對MySql的產品1實現
public class MysqlDaoFactory implements IFactoryDao {private static IFactoryDao factory = new MysqlDaoFactory();private MysqlDaoFactory() { }public static IFactoryDao getInstance() {return factory;}@Overridepublic IAddressDao createAddressDao() {return new AddressMySqlDao();}@Overridepublic IUserDao createUserDao() {return new UserMySqlDao();}}//工廠實現2(MySql)
由兩個工廠可以發現,兩個工廠里的產品都是產品族(AddressMySqlDao和AddressJDBCDao是同一個接口的實現)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在項目中調用工廠1或2也要修改代碼,這也不好,因此可以用反射。把要創建的工廠className寫在配置文件這樣只需修改配置文件即可,靈活、不破壞封裝性、ocp。
package com.yan.factory.dao;import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Properties;public class DaoUtil {public static IFactoryDao createDaoFactory() {IFactoryDao f = null;try {Properties prop = PropertiesUtil.getDaoProp();String fs = prop.getProperty("factory");Class clz = Class.forName(fs);String mn = "getInstance";Method m = clz.getMethod(mn);f = (IFactoryDao)m.invoke(clz);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}return f;} }dao.properties文件
在項目中private IAddressDao addressDao = DaoUtil.createDaoFactory().createAddressDao();即可
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
上面有點缺點就是太繁雜,要創建多個工廠實例,我們可以利用反射,只創建一個工廠,把要創建的Dao寫在配置文件
package com.yan.factory.dao;import java.util.HashMap; import java.util.Map; import java.util.Properties;public class PropertiesFactory implements IFactoryDao {private static PropertiesFactory f = new PropertiesFactory();private PropertiesFactory() { }public static IFactoryDao getInstance() {return f;}@Overridepublic Object getDao(String name) {try {Properties prop = PropertiesUtil.getDaoProp();String cn = prop.getProperty(name);Object obj = Class.forName(cn).newInstance();System.out.println(obj);return obj;} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return null;}}factory=com.yan.factory.dao.PropertiesFactory UserDao="com.yan.factory.dao.UserJDBCDao"
總結
以上是生活随笔為你收集整理的工厂模式及在项目中的应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java类为什么要序列化_Java 中的
- 下一篇: A* 算法讲解