①:将对象的创建过程封装在工厂类中,使对象复杂的创建过程与程序业务逻辑解耦
②:屏蔽产品类,用户只需关心产品的接口,只要接口保持不变,系统中的上层模块就不需要变化(如jdbc驱动)。
- 简单工厂模式:一个factory负责所有产品的创建(1:N),不易扩展
- 工厂方法模式:N个factory负责M个产品的创建(N:M),易扩展,但容易导致类文件数量爆炸
- 抽象工厂模式:N个factory负责N类产品的创建,而factory的方法又对应单类产品的M个型号(N:N:MN)
简单工厂模式
当工厂类中创建对象的逻辑较为简单且稳定时,可采用简单工厂模式。
由于简单工厂模式将创建逻辑都封装在单一的方法中,因此工厂类的扩展只能修改其创建逻辑相关代码,不易扩展
// 简单工厂模式
public static <T extends IHuman> T createHuman(String color){
IHuman human = null;
if("white".equals(color)){
human = new WhiteHuman();
}else if("yellow".equals(color)){
human = new YellowHuman();
}else if("black".equals(color)){
human = new BlackHuman();
}
return (T)human;
}
工厂方法模式
当工厂类中创建对象的逻辑较为复杂时,可定义一个创建对象的接口,由子类实现创建的逻辑,用户根据需要的产品选择对应工厂子类。(易于扩展,新增产品种类只需新增对应的工厂实例)
// jdbc就采用了工厂方法模式:Driver类是AbstractFactory类,而不同数据库都需要实现Driver并注册到DriverManager中,driver创建的产品即为Connection
// 唯一的不同是,jdbc中遍历了所有的Driver实例去判断对应的url适用于哪种Driver生成的conn.
for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) {
try {
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
}
}
抽象工厂模式
当创建的对象,存在多个维度的区别时(产品簇),定义一个创建对象的接口,接口的实现延申出一个维度,而接口方法延申出另一个维度
抽象工厂模式特点:在接口方法延申的维度上,①:可以设置非公开状态的约束 ②:此维度扩展困难
根据维度划分的不同,可能有:
方案一:根据不同肤色创建不同的工厂,{Color}Factory{createMan(),createWoman}方案二:根据不同性别创建不同的工厂,{Sex}Factory{createWhite(),createYellow(),createBlack()}
额外添加createMan()/createWoman()方法,可以根据需要,协调不同品类产品的比例(非公开状态的约束)
池化技术(工厂模式+有限多例)
public abstract Pool{
private Vector<Connection> freeConnections = new Vector<>(); // 存放空闲线程的容器
private int maxConnect = 100; // 最大连接数
private int normalConnect = 10; // 常驻连接数
private static int checkedOut= 0; // 正在使用的连接数
// 单例模式连接池
private static Pool pool = null; // 存放连接池单例变量
public static synchronized Pool getInstance();
private DBConnectionPool();
// 新建链接
private Connection newConnection();
// 获得链接
public Connection getConnection();
// 释放链接
public void freeConnection(Connection conn);
// 展示当前连接池状态
public PoolStatus status();
// 销毁连接池
public void release();
}