现在我们有一个简单需求要是实现一个数据库连接,而JDBC可以给我们一个很好的思路
//伪代码片段
public class ConnectionFactory {
public static Connection create(String type,Properties p){
if ("mySql".equals(type)){
return new MySqlConnection(p);
}
if ("Oracle".equals(type)){
return new OracleConnection(p);
}
}
}
通过这段简单的伪代码我们可以看出我们将创建连接的细节封装了起来,我们只需要传入我们需要的数据库名称以及连接的信息就能获取到我们想要的连接,就像一座工厂一样,我们不需要知道对象创建的细节。我们只需要描述我们的需求(即传入的参数)工厂就会帮我们创建满足我们要求的产品。类图如下:
这种方式很简单的实现我们的需求,但他的缺点也是明显的,当现在我们需要新的数据库,我们还需要其他的数据库连接时,我们就需要修改ConnectionFactory中的方法,来满足我们的需求。这咋一看其实没有什么的,不就是再加一个if判断,但当这段但代码不是你写的或是已经被打成jar包无法修改时,那么这个问题就比较严重了。扩展性的不足的特点就体现的很明显了。
针对这个问题我们可以通过配置文件来增加我们代码的灵活性
public class ConnectionFactory {
public static Connection create(String type,Properties p){
Class > clz = getConnectionClass(type);
Constructor> c = clz.getConstructor(Properties.class);
return c.newInstance(p)
}
public Class getConnectionClass(String type){
return null;
}
}
配置文件中写法: mysql = com.connection.MySQLConnectionimpl //连接的实现类
//数据信息略
通过配置文件,我们可以极大提高代码的灵活性,及时ConnectionFactory代码不能修改,我们也可以通过配置文件来实现我们的扩展。
通过上述的方法其实已经能够满足我们的要求了,但是我们的目的不仅仅如此,简单工厂方法只是一个引子,用它是为了引出我们的工厂方法。我们还是已JDBC作为背景 如图
刚才我们的ConnectionFactory是一个实现类,具体的实现都在ConnectionFactory中实现,而现在我们把ConnectionFactor抽象为一个接口,将实现分离出来。我们只提供接口,而具体的实现有各个数据库厂家来实现
public interface ConnectionFactory{
public Connection create (Properties info)
}
public class MySQLConnectionFactory implements ConnectionFactory{
public Connection create(Properties info){
return new MySQLConnection(info);
}
}
//第一种方式获取我们想要的连接
Class > clz = Class.forName("com.connection.MySQLConnectionFactory");
ConnectionFactory connectionFactory = (Connection)clz.newInstance();
Properties info = new Properties();
info.put("host","localhost");
info.put("port",8080);
info.put("dataBase","e3tms");
into.put("user","root");
into.put("password","124");
Connection con = connectionFactory.create(info);
这种方式使我们前进了一步,只是我们作为调用方不必知道太多的细节,譬如创建工厂对象。JDBC的处理方法就是加了一个中间对象来管理这些细节操作
public class ConnectionFactoryManager{
private List factories = new ArrayList();
public static Connection getConnection(String url,String userName,String passWord){
for (ConnectionFactory factory: factories){
Connection con = factory.create(url,userName,password);
if (conn != null){
return conn;
}
}
throw new RuntimeException("can't create connection");
}
public static void register(ConnectionFactory factory){
factories.add(factory);
}
}
public class MySQLConnectionFactory implements ConnectionFactory{
static{
ConnectionFactoryManager.register(new MySQLConnectionFactory())
}
public Connection create(String url,String userName,String password){
if(accpet(url)){
//创建MyConnection
}
return null;
}
public boolean accpetURL(String url){
url.startWith("jdbc:mysql");
}
}
//创建数据库连接对象
Class > clz = Class.forName("com.connection.MySQLConnectionFactory");
MySQLConnection con = ConnectionFactoryManager.getConnection(url,userName,password);
至此我们的模拟实现全部完成了。通过模拟JDBC让我们很好的理解了工厂方法。