今天杨哥给小伙们带来了抽象工厂模式,杨哥使用一个经典的案例来讲解该模式、在我们开发中,尤且是服务端开发的小伙们,由于公司的业务或成本的需要,经常更换数据库,所以怎么做到灵活更换数据库的问题摆在了开发者们,那么我们就需要一个很好的设计模式、杨哥认为可以使用抽象工厂模式解决该业务场景。
这是使用了抽象工厂模式访问数据库的UML类图
下面是类图中的几个类:
User类:
package chouxianggongchang_designmode;
public class User {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
}
Department类:
package chouxianggongchang_designmode;
public class Department {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
private String deptName;
}
IUser接口:
package chouxianggongchang_designmode;
public interface IUser {
void Insert(User user);
User GetUser(int id);
}
IUser实现类AccessUser:
package chouxianggongchang_designmode;
public class AccessUser implements IUser{
public void Insert(User user)
{
System.out.println("在Access中给User表增加一条记录");
}
public User GetUser(int id)
{
System.out.println("在Access中根据ID得到User表一条记录");
return null;
}
}
IUser实现类SqlserverUser:
package chouxianggongchang_designmode;
public class SqlserverUser implements IUser{
public void Insert(User user)
{
System.out.println("在Sqlserver中给User表增加一条记录");
}
public User GetUser(int id)
{
System.out.println("在Sqlserver中根据ID得到User表一条记录");
return null;
}
}
IDepartment接口:
package chouxianggongchang_designmode;
public interface IDepartment {
void Insert(Department department);
Department GetDepartment(int id);
}
IDepartment实现类SqlserverDepartment:
package chouxianggongchang_designmode;
public class SqlserverDepartment implements IDepartment{
public void Insert(Department department)
{
System.out.println("在Sqlserver中给Department表增加一条记录");
}
public Department GetDepartment(int id)
{
System.out.println("在Sqlserver中根据ID得到Department表一条记录");
return null;
}
}
IDepartment实现类AccessDepartment :
package chouxianggongchang_designmode;
public class AccessDepartment implements IDepartment{
public void Insert(Department department)
{
System.out.println("在Access中给Department表增加一条记录");
}
public Department GetDepartment(int id)
{
System.out.println("在Access中根据ID得到Department表一条记录");
return null;
}
}
IFactory接口:定义一个创建访问User表的对象的抽象的工厂接口
package chouxianggongchang_designmode;
public interface IFactory {
IUser CreateUser();
IDepartment CreateDepartment();//增加的接口方法
}
SqlServerFactory工厂类:
package chouxianggongchang_designmode;
public class SqlServerFactory implements IFactory{
public IUser CreateUser()
{
return new SqlserverUser();
}
//增加了SqlserverDepartment()工厂
public IDepartment CreateDepartment()
{
return new SqlserverDepartment();
}
}
AccessFactory工厂类:
package chouxianggongchang_designmode;
public class AccessFactory implements IFactory{
public IUser CreateUser()
{
return new AccessUser();
}
//增加了AccessDepartment()工厂
public IDepartment CreateDepartment()
{
return new AccessDepartment();
}
}
Main函数:
package chouxianggongchang_designmode;
public class AbstractFactory {
public static void main(String[] args) {
User user = new User();
Department dept = new Department();
//AbstractFactory factory = new SqlServerFactory();//只需要确定实例化哪一个数据访问对象给工厂即可
IFactory factory = new AccessFactory();
IUser iu = factory.CreateUser();//此时与具体的数据库访问对象解除了依赖
iu.Insert(user);
iu.GetUser(1);
IDepartment id = factory.CreateDepartment();//此时与具体的数据库访问对象解除了依赖
id.Insert(dept);
id.GetDepartment(1);
}}
运行效果:
原理:
抽象工厂模式,提供一个创建一系列的相关或相互依赖的对象的接口,而无需指定它们具体的类。
总结:
AbstractProductA和AbstractProduct是两个抽象的产品,之所以为抽象,是因为它们都有可能有两种不同的实现,就是刚才的上面的例子来说是User和Department,而ProductA1、ProductA2和ProductB1和ProductB2就是对两个抽象产品的具体分类的实现,比如ProductA1可以理解为是SqlserverUser,而ProductB1是AccessUser。
这么说,IFactory是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法。而ConcreteFactory1和ConcreteFactory2就是具体的工厂。就像SqlserverFactory和AccessFactory一样。
通常是在运行时刻再创建一个ConcreteFactory类的实例,这个具体的工厂再创建具有特定实现的产品对象,也就是说,为创建不同的产品对象,客户端应使用不同的具体工厂。