目录
1.抽象工厂的概念
提供一个创建一系列相关或互相依赖的对象的接口,而无需指定他们具体的类
2.抽象工厂的结构图
3.抽象工厂设计模式的练习示例
数据库的用户类:
/**
* 数据库的用户类
*/
@Data
public class User {
private int id;
private String userName;
}
部门类:
/**
* 部门类
*/
@Data
public class Department {
private int id;
private String deptName;
}
操作部门表的抽象数库:
/**
* 操作部门表的抽象数据库
*/
interface IDepartment {
void insert(Department department);
Department get(int id);
}
操作用户表的抽象数据库:
/**
* 操作用户表的抽象数据库
*/
interface IUser {
void insert(User user);
User getUser(int id);
}
操作用户表的mysql数据库:
/**
* 操作用户表的mysql数据库
*/
public class MysqlUser implements IUser{
@Override
public void insert(User user) {
System.out.println("MysqlUser在数据库内增加了一位用户");
}
@Override
public User getUser(int id) {
System.out.println("MysqlUser从数据库内获得了一条数据");
return new User();
}
}
操作部门表的mysql数据库:
/**
* 操作部门表的mysql数据库
*/
public class MysqlDepartment implements IDepartment{
@Override
public void insert(Department department) {
System.out.println("MysqlDepartment在数据库内增加了一条数据");
}
@Override
public Department get(int id) {
System.out.println("MysqlDepartment从数据库查询了一条数据");
return null;
}
}
操作用户表的oracle数据库:
/**
* 操作用户表的oracle数据库
*/
public class OracleUser implements IUser{
@Override
public void insert(User user) {
System.out.println("OracleUser在数据库内增加了一条数据");
}
@Override
public User getUser(int id) {
System.out.println("OracleUser从数据库内查询了一条数据");
return null;
}
}
操作部门表的oracle数据库:
/**
* 操作部门表的oracle数据库
*/
public class OracleDepartment implements IDepartment{
@Override
public void insert(Department department) {
System.out.println("OracleDepartment在数据库内增加了一条数据");
}
@Override
public Department get(int id) {
System.out.println("OracleDepartment从数据库内查询了一条数据");
return new Department();
}
}
定义一个创建操作用户表,部门表的数据库对象的抽象工厂接口:
/**
* 定义一个创建操作用户表,部门表的数据库对象的抽象工厂接口
*/
interface IFactory {
IUser createUser();
IDepartment createDepartment();
}
创建一个生产mysql用户的工厂:
/**
* 创建一个生产mysql用户的工厂
*/
public class MysqlFactory implements IFactory{
@Override
public IUser createUser() {
return new MysqlUser();
}
@Override
public IDepartment createDepartment() {
return new MysqlDepartment();
}
}
创建一个生产oracle用户的工厂:
/**
* 创建一个生产oracle用户的工厂
*/
public class OracleFactory implements IFactory{
@Override
public IUser createUser() {
return new OracleUser();
}
@Override
public IDepartment createDepartment() {
return new OracleDepartment();
}
}
测试:
public class Test {
public static void main(String[] args) {
//创建一个用户
User user = new User();
//创建一个部门
Department department = new Department();
//使用抽象工厂创建一个 生产 操作用户表,部门表的mysql数据库对象 的工厂
IFactory iFactory = new MysqlFactory();
//工厂创建操作用户表的mysql数据库对象
IUser user1 = iFactory.createUser();
//操作用户表的mysql数据库对象操作用户表
user1.getUser(1);
user1.insert(user);
//工厂创建操作部门表的mysql数据库对象
IDepartment department1 = iFactory.createDepartment();
//操作部门表的mysql数据库对象操作部门表
department1.get(1);
department1.insert(department);
}
}
4.抽象工厂设计模式的练习示例结构图
5. 抽象工厂 + 反射 + 配置文件
5.1:什么是java的反射机制?
JAVA反射机制是就是运行的状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。通过反射机制可以动态的访问类的属性和方法以及字段。
5.2:抽象工厂与反射
抽象工厂通常和java的反射机制紧密联系在一起。当遇到新的具体产品角色出现时,如果没有java的反射机制,我们需要首先要修改抽象工厂中的代码,然后创建具体的工厂类,在UI(客户端)修改相关代码, 将具体的工厂的实例化代码加入。严重违反了开闭原则。但是通过java的反射机制就可以将抽象工厂模式的实现对修改封闭,在拓展开放,将新的具体的工厂类名的写入配置文件中,通过读取配置文件就可以读取到新增的具体工厂的类名,根据类名自动生成相应类的实例化。
5.3:抽象工厂 + 反射 + 配置文件 的结构图
![](https://i-blog.csdnimg.cn/blog_migrate/15243b5b22e61d2fb475683a3704b782.png)
5.4:练习实例:
Data类:
/**
* 抽象工厂 + 反射 + 配置文件
*/
@Component
public class Data {
private static String dataBase;
public static IUser getUser() throws Exception{
Properties properties = new Properties();
InputStream resourceAsStream = Data.class.getClassLoader().getResourceAsStream("application.properties");
properties.load(resourceAsStream);
String className = "com.example.designpatternexer.abstractfactory." + properties.get("dataBase") + "User";
Class<IUser> iUserClass = (Class<IUser>) Class.forName(className);
return iUserClass.getConstructor().newInstance();
}
public static IDepartment getDepartment() throws Exception{
Properties properties = new Properties();
InputStream resourceAsStream = Data.class.getClassLoader().getResourceAsStream("application.properties");
properties.load(resourceAsStream);
String className = "com.example.designpatternexer.abstractfactory."+ properties.get("dataBase") + "Department";
Class<IDepartment> iUserClass = (Class<IDepartment>) Class.forName(className);
return iUserClass.getConstructor().newInstance();
}
}
测试类:
public class Test2 {
public static void main(String[] args) {
try {
User user1 = new User();
Department department = new Department();
IUser user = Data.getUser();
user.insert(user1);
user.getUser(1);
IDepartment department1 = Data.getDepartment();
department1.insert(department);
department1.get(1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
配置文件:
控制台:
6.总结:
现在如果我们增加了SqlServer 数据库访问,相关的类的增加是不可避免的,这点无论我们用任何办法都解决不了,不过这叫扩展,开放-封闭原则性告诉我们,对于扩展,我们开放。但对于修改,我们应该要尽量关闭,就目前而言,我们只需要更改private static string dataBase在配置文件中的值就行了。也就意味着就这一句话发生了改变。
尚硅谷设计模式视频下对于工厂方法与抽象工厂区别的总结:
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个