首页 > 学院 > 开发设计 > 正文

工厂模式及在项目中的应用

2019-11-11 05:41:03
字体:
来源:转载
供稿:网友

工厂模式分为简单工厂、工厂方法模式和抽象工厂模式。简单工厂顾名思义是最简单的,从一个工厂获取所需的产品类似于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 {	@Override	public void add(User user) {		System.out.println("UserJDBCDao....add");	}	@Override	public void delete(int id) {		System.out.println("UserJDBCDao....delete");	}	@Override	public void update(User user) {		System.out.println("UserJDBCDao....update");	}}//针对JDBC的产品2实现
public class AddressJDBCDao implements IAddressDao {	@Override	public void add(Address address, int userId) {		System.out.println("addressJDBCDao....add");	}	@Override	public void update(Address address) {		System.out.println("addressJDBCDao....update");	}	@Override	public 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;	}	@Override	public IUserDao createUserDao() {		return new UserJDBCDao();	}	@Override	public IAddressDao createAddressDao() {		return new AddressJDBCDao();	}}//工厂接口实现1(JDBC)
public class UserMySQLDao implements IUserDao {	@Override	public void add(User user) {		System.out.println("UserMySqlDao....add");	}	@Override	public void delete(int id) {		System.out.println("UserMySQlDao....delete");	}	@Override	public void update(User user) {		System.out.println("UserMySqlDao....update");	}	}//针对MySql的产品2实现
public class AddressMySqlDao implements IAddressDao {	@Override	public void add(Address address, int userId) {		System.out.println("addressMySqlDao....add");	}	@Override	public void update(Address address) {		System.out.println("addressMySqlDao...update");	}	@Override	public 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;	}		@Override	public IAddressDao createAddressDao() {		return new AddressMySqlDao();	}	@Override	public 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文件

factory=com.yan.factory.dao.JDBCDaoFactory可修改配置文件测试。

在项目中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;	}	@Override	public 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.PropertiesFactoryUserDao="com.yan.factory.dao.UserJDBCDao"


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表