某公司经常会接到类似的项目,可能只是使用不同的数据库。所以在设计项目的时候,为了提高代码的可重用性,减少代码的耦合性,针对上面的情况,我们使用抽象工厂模式。
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
1、User类
public class User
{
private int userID;
private String userName;
public int getUserID()
{
return userID;
}
public void setUserID(int userID)
{
this.userID = userID;
}
public String getUserName()
{
return userName;
}
public void setUserName(String userName)
{
this.userName = userName;
}
}
2、department类
public class Department
{
private int departmentID;
private String departmentName;
public int getDepartmentID()
{
return departmentID;
}
public void setDepartmentID(int departmentID)
{
this.departmentID = departmentID;
}
public String getDepartmentName()
{
return departmentName;
}
public void setDepartmentName(String departmentName)
{
this.departmentName = departmentName;
}
}
3、IUser接口
public interface IUser
{
void insert(User user);
User getUser(int id);
}
4、IDepartment接口
interface IDepartment
{
void insert(Department department);
Department getDepartment(int id);
}
5、IFactory接口
interface IFactory
{
IUser createUser();
IDepartment createDepartment();
}
6、SQLServerDepartment连接SQLserver的类
public class SQLServerDepartment implements IDepartment
{
@Override
public void insert(Department department)
{
// TODO Auto-generated method stub
System.out.println("在SQL Server中给Department表增加一条记录");
}
@Override
public Department getDepartment(int id)
{
System.out.println("在SQL Server中根据ID得到Department表的一条记录");
return null;
}
}
7、SQLServerUser类
public class SQLServerUser implements IUser
{
@Override
public void insert(User user)
{
// TODO Auto-generated method stub
System.out.println("在SQL Server中给User表增加一条记录");
}
@Override
public User getUser(int id)
{
// TODO Auto-generated method stub
System.out.println("在SQL Server中根据ID得到User表的一条记录");
return null;
}
}
8、SQLServerFactory
public class SQLServerFactory implements IFactory
{
@Override
public IUser createUser()
{
// TODO Auto-generated method stub
return new SQLServerUser();
}
@Override
public IDepartment createDepartment()
{
// TODO Auto-generated method stub
return new SQLServerDepartment();
}
9、AccessUser类
public class AccessUser implements IUser
{
@Override
public void insert(User user)
{
// TODO Auto-generated method stub
System.out.println("在Access中给User表增加一条记录");
}
@Override
public User getUser(int id)
{
// TODO Auto-generated method stub
System.out.println("在Access中根据ID得到User表的一条记录");
return null;
}
}
10、AccessDepartment类
public class AccessDepartment implements IDepartment
{
@Override
public void insert(Department department)
{
// TODO Auto-generated method stub
System.out.println("在Access中给Department表增加一条记录");
}
@Override
public Department getDepartment(int id)
{
System.out.println("在Access中根据ID得到Department表的一条记录");
return null;
}
}
11、AccessFactory类
public class AccessFactory implements IFactory
{
@Override
public IUser createUser()
{
// TODO Auto-generated method stub
return new AccessUser();
}
@Override
public IDepartment createDepartment()
{
// TODO Auto-generated method stub
return new AccessDepartment();
}
}
12、客户端程序
public class Client
{
public static void main(String[] args)
{
User user=new User();
Department dept=new Department();
IFactory factory=new SQLServerFactory();
IFactory factory1=new AccessFactory();
IUser Iu=factory.createUser();
Iu.insert(user);
Iu.getUser(1);
IDepartment Idept=factory1.createDepartment();
Idept.insert(dept);
Idept.getDepartment(1);
}
}
抽象工厂模式的优缺点:
优点:
1)易于交换产品系列,由于具体工厂类,例如IFactory factory=new AccessFactory();在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。
2)它让具体额创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出席在客户端代码中。
缺点:如果要增加新的功能或者客户端的类非常多,需要添加和更改的代码就非常多。
改进:用反射+抽象工厂的数据访问模式
将IFactory、SQLServerFactory、AccessFactory三个工厂类用DataAccess来代替。
DataAccess类
public class DataAccess
{
private static String nameSpace="cn.sict.abstractfactory.example1";
private static String DB="SQLServer";
public static IUser createUser() throws Exception
{
String className=nameSpace+"."+DB+"User";
return (IUser)Class.forName(className).newInstance();
}
public static IDepartment createDepartment() throws Exception
{
String className=nameSpace+"."+DB+"Department";
return (IDepartment)Class.forName(className).newInstance();
}
}
客户端程序
ublic class Client1
{
public static void main(String[] args) throws Exception
{
User user=new User();
Department dept=new Department();
IUser iu=DataAccess.createUser();
iu.insert(user);
iu.getUser(1);
IDepartment id=DataAccess.createDepartment();
id.insert(dept);
id.getDepartment(1);
}
}
还可以将DB的值放在配置文件中,通过读取配置文件的值来进行赋值。
参考文献:程杰老师<大话设计模式>