定義:提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類
通常是在運行時刻再創建一個concreteFactory
類的實例,這個具體工廠再創建具有特定實現的產品對象,也就是說,爲創建不同的產品對象,客戶端應使用不同的具體工廠
所有在用簡單工廠的地方,都可以考慮用反射技術來去除switch
或if
,解除分支判斷帶來的耦合
反射技術可以將簡單工廠中的判斷去除,進一步解放代碼。
先看個例子,慢慢解釋
先是一個用戶表,可能會存在多個字段,這裏只用id 與name 示例
class User
{
private int id;
private String name;
// getter && setter
}
用戶表可能的操作,這裏只示意插入與查詢
public interface IUser
{
void insert(User user);
User getUser(int id);
}
另外一個表,同用戶表,這裏用部門表示例做區分,用以擴展業務
public class Department
{
private String name;
// getter && setter
}
部門表的不同操作
public interface IDepartment
{
void insert(Department department);
Department getDepartment(String name);
}
定義不同數據庫操作方法的接口
interface IFactory
{
IUser createUser();
}
具體數據庫連接 SQLServer
class SqlServerFactory implements IFactory
{
public IUser createUser()
{
return new SqlServerUser();
}
}
具體數據庫連接 Access
class AccessFactory implements IFactory
{
public IUser createUser()
{
return new Accessuser();
}
}
SqlServer
用戶操作實現方法
class SqlServerUser implements IUser
{
public void insert(User user)
{
System.out.println("sql server insert user");
}
public User getUser(int id)
{
System.out.println("get user from sql server");
return null;
}
}
SqlServer
部門表的操作實現方法
public class SqlServerDepartment implements IDepartment
{
public void insert(Department department)
{
System.out.println("insert department to sqlserver");
}
public Department getDepartment(String name)
{
System.out.println("get department from sqlserver");
return null;
}
}
Access
用戶操作方法
class Accessuser implements IUser
{
public void insert(User user)
{
System.out.println("access insert user");
}
public User getUser(int id)
{
System.out.println("get user from access");
return null;
}
}
Access
部門表的操作方法
public class AccessDepartment implements IDepartment
{
public void insert(Department department)
{
System.out.println("insert into access a department");
}
public Department getDepartment(String name)
{
System.out.println("get a department from access");
return null;
}
}
管理所有數據庫連接的獲取,這裏用了兩個方式
switch
關鍵詞直接判斷,可用- 利用反射技術,此示例代碼會拋出異常,因爲配置的類的全路徑需要修改,項目中是需要使用配置文件的,也就不會有此問題
public class DataAccess
{
private static db d = db.SqlServer;
public static IUser createUser()
{
IUser result = null;
try
{
result = (IUser) Class.forName(d.toString()).newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
if (result != null)
{
return result;
}
switch (d)
{
case SqlServer:
result = new SqlServerUser();
break;
case Access:
result = new Accessuser();
break;
default:
break;
}
return result;
}
public static IDepartment createDepartment()
{
IDepartment result = null;
try
{
result = (IDepartment) Class.forName(d.toString()).newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
if (result != null)
{
return result;
}
switch (d)
{
case SqlServer:
result = new SqlServerDepartment();
break;
case Access:
result = new AccessDepartment();
break;
default:
break;
}
return result;
}
}
enum db
{
SqlServer, Access
}
客戶端代碼就比較簡單了,此模式要實現的目的就是讓客戶端成爲傻逼,只要做事就可以了,其他的由配置完成,客戶端調用時完全無感,這樣如果增加新的數據庫,只要實現IFactory
接口獲取連接、實現IUser
獲取對用戶表的操作、實現IDepartment
獲取對部門表的操作就可以。
沒辦法,改換數據庫是個大工程,必須要有修改,我們要實現的目的就是將修改減至最少
public class AbstractFactoryMain
{
public static void main(String[] args)
{
User user = new User();
Department dept = new Department();
IUser iu = DataAccess.createUser();
iu.insert(user);
iu.getUser(1);
IDepartment department = DataAccess.createDepartment();
department.insert(dept);
department.getDepartment("le");
}
}
總結:此模式名爲抽象工廠,區別與前面的工廠模式的就是這裏的工廠方法也是抽象的,可以有多個不同的具體工廠