当我们获取数据库连接(mysql,oracle,db2)的时候,一般会用到这样的代码:
DbConnection getConnection(String type){
DbConnection dc;
if(type.equals("mysql")){
dc=new MySqlConnection();
}else if(type.equals("oracle")){
dc=new OracleConnection();
}else if(type.equals("db2")){
dc=new Db2Connection();
}
//对连接进行初始化、准备工作、正式连接
dc.init();
dc.prepare();
dc.connect();
return dc;
}
问题:
当有新的连接类型,或者要去除某些数据库连接,我们需要修改代码。
以上代码没有对修改关闭。
解决方法:
在getConnection方法中封装创建连接的代码(createConnection),
把创建连接的代码移到另一个对象中,由这个对象专门创建连接。我们称这个对象为“工厂”。
我们的设计应该:对扩展开放,对修改关闭。
简单工厂:无法由子类决定要实例化的类是哪一个,没有依赖抽象。
package com.ez.biz;
import com.ez.DbConnection;
/**
* @author 窗外赏雪(EZ编程网)
*/
public class FactoryTest {
public static void main(String[] args) {
SimpleDbConnectionFactory factory=new SimpleDbConnectionFactory();
//注入简单工厂
DbUnit dbUnit=new DbUnit(factory);
DbConnection connection = dbUnit.getConnection("mysql");
System.out.println("==============================");
connection = dbUnit.getConnection("oracle");
System.out.println("==============================");
connection = dbUnit.getConnection("db2");
System.out.println("==============================");
}
}
package com.ez.biz;
import com.ez.DbConnection;
/**
* 获取数据库连接
* @author 窗外赏雪(EZ编程网)
*/
public class DbUnit {
SimpleDbConnectionFactory factory;
public DbUnit(SimpleDbConnectionFactory factory) {
this.factory=factory;
}
public DbConnection getConnection(String type){
DbConnection dbConnection;
//通过传入数据库类型,使用工厂创建对应数据库的连接
dbConnection=factory.createDbConnection(type);
dbConnection.init();
dbConnection.prepare();
dbConnection.connect();
return dbConnection;
}
}
package com.ez.biz;
import com.ez.DbConnection;
import com.ez.impl.Db2Connection;
import com.ez.impl.MySqlConnection;
import com.ez.impl.OracleConnection;
/**
* 创建数据库连接的工厂类
* @author 窗外赏雪(EZ编程网)
*/
public class SimpleDbConnectionFactory {
public DbConnection createDbConnection(String type){
DbConnection dbConnection=null;
if("mysql".equals(type)){
dbConnection=new MySqlConnection();
}else if("oracle".equals(type)){
dbConnection=new OracleConnection();
}else if("db2".equals(type)){
dbConnection=new Db2Connection();
}
return dbConnection;
}
}
package com.ez;
/**
* 数据库连接接口,所有数据库连接必须实现该接口
* @author 窗外赏雪(EZ编程网)
*/
public abstract class DbConnection {
public void init(){
System.out.println("DbConnection init");
}
public void prepare(){
System.out.println("DbConnection prepare");
}
public void connect(){
System.out.println("DbConnection connect");
}
}
package com.ez.impl;
import com.ez.DbConnection;
/**
* DB2数据库连接
* @author 窗外赏雪(EZ编程网)
*/
public class Db2Connection extends DbConnection{
public void connect(){
System.out.println("Db2Connection connect");
}
}
package com.ez.impl;
import com.ez.DbConnection;
/**
* mysql数据库连接
* @author 窗外赏雪(EZ编程网)
*/
public class MySqlConnection extends DbConnection{
public void connect(){
System.out.println("MySqlConnection connect");
}
}
package com.ez.impl;
import com.ez.DbConnection;
/**
* oracle数据库连接
* @author 窗外赏雪(EZ编程网)
*/
public class OracleConnection extends DbConnection{
public void connect(){
System.out.println("OracleConnection connect");
}
}
静态工厂:用静态方法定义一个简单的工厂,静态工厂不能通过继承(多态)来改变创建方法的行为。
工厂模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
工厂模式能够封装具体类型的实例化。
抽象的Dbunit类提供了一个创建对象的抽象方法,也称为“工厂方法”。在抽象的Dbunit中,任何其他实现的方法,如:getConnection(),都可以使用这个工厂方法所制造出来的产品,但是只有子类真正实现这个工厂方法并创建产品。
package com.ez.biz;
import com.ez.DbConnection;
/**
* 工厂模式测试类
* @author 窗外赏雪(EZ编程网)
*/
public class FactoryTest {
public static void main(String[] args) {
DbUnit dbUnit=new NewDbUnit();
DbConnection connection = dbUnit.getConnection("mysql");
connection = dbUnit.getConnection("oracle");
connection = dbUnit.getConnection("db2");
System.out.println("==============================");
dbUnit=new OldDbUnit();
connection = dbUnit.getConnection("mysql");
connection = dbUnit.getConnection("oracle");
connection = dbUnit.getConnection("db2");
}
}
package com.ez.biz;
import com.ez.DbConnection;
/**
* 这是抽象创建者,定义了一个抽象的工厂方法,让子类实现此方法制造产品。
* @author 窗外赏雪(EZ编程网)
*/
public abstract class DbUnit {
public DbConnection getConnection(String type){
DbConnection dbConnection;
//通过传入数据库类型,使用工厂创建对应数据库的连接
dbConnection=createDbConnection(type);
dbConnection.init();
dbConnection.prepare();
dbConnection.connect();
return dbConnection;
}
/**
* 抽象的工厂方法,让子类实现此方法制造产品。
* @param type
* @return
*/
public abstract DbConnection createDbConnection(String type);
}
package com.ez.biz;
import com.ez.DbConnection;
import com.ez.impl.NewDb2Connection;
import com.ez.impl.NewMySqlConnection;
import com.ez.impl.NewOracleConnection;
/**
* 新版本的数据库连接,子类实现方法制造产品。
* @author 窗外赏雪(EZ编程网)
*/
public class NewDbUnit extends DbUnit{
@Override
public DbConnection createDbConnection(String type) {
DbConnection dbConnection = null;
if("mysql".equals(type)){
dbConnection = new NewMySqlConnection();
}else if("oracle".equals(type)){
dbConnection = new NewOracleConnection();
}else if("db2".equals(type)){
dbConnection = new NewDb2Connection();
}
return dbConnection;
}
}
package com.ez.biz;
import com.ez.DbConnection;
import com.ez.impl.OldDb2Connection;
import com.ez.impl.OldMySqlConnection;
import com.ez.impl.OldOracleConnection;
/**
* 老版本的数据库连接,子类实现方法制造产品。
* @author 窗外赏雪(EZ编程网)
*/
public class OldDbUnit extends DbUnit{
@Override
public DbConnection createDbConnection(String type) {
DbConnection dbConnection = null;
if("mysql".equals(type)){
dbConnection = new OldMySqlConnection();
}else if("oracle".equals(type)){
dbConnection = new OldOracleConnection();
}else if("db2".equals(type)){
dbConnection = new OldDb2Connection();
}
return dbConnection;
}
}
package com.ez;
/**
* 数据库连接接口,所有数据库连接必须实现该接口
* @author 窗外赏雪(EZ编程网)
*/
public abstract class DbConnection {
public void init(){
System.out.println("DbConnection init");
}
public void prepare(){
System.out.println("DbConnection prepare");
}
public void connect(){
System.out.println("DbConnection connect");
}
}
package com.ez.impl;
import com.ez.DbConnection;
/**
* 新版本的DB2数据库连接
* @author 窗外赏雪(EZ编程网)
*/
public class NewDb2Connection extends DbConnection{
public void connect(){
System.out.println("NewDb2Connection connect");
}
}
package com.ez.impl;
import com.ez.DbConnection;
/**
* 新版本的mysql数据库连接
* @author 窗外赏雪(EZ编程网)
*/
public class NewMySqlConnection extends DbConnection{
public void connect(){
System.out.println("NewMySqlConnection connect");
}
}
package com.ez.impl;
import com.ez.DbConnection;
/**
* 新版本的oracle数据库连接
* @author 窗外赏雪(EZ编程网)
*/
public class NewOracleConnection extends DbConnection{
public void connect(){
System.out.println("NewOracleConnection connect");
}
}
package com.ez.impl;
import com.ez.DbConnection;
/**
* 老版本的DB2数据库连接
* @author 窗外赏雪(EZ编程网)
*/
public class OldDb2Connection extends DbConnection{
public void connect(){
System.out.println("OldDb2Connection connect");
}
}
package com.ez.impl;
import com.ez.DbConnection;
/**
* 老版本的mysql数据库连接
* @author 窗外赏雪(EZ编程网)
*/
public class OldMySqlConnection extends DbConnection{
public void connect(){
System.out.println("OldMySqlConnection connect");
}
}
package com.ez.impl;
import com.ez.DbConnection;
/**
* 老版本的oracle数据库连接
* @author 窗外赏雪(EZ编程网)
*/
public class OldOracleConnection extends DbConnection{
public void connect(){
System.out.println("OldOracleConnection connect");
}
}
我们使用工厂来创建连接,通过传入不同的工厂,可以创建出不同的连接。但是客户端代码始终不变。
package com.ez.biz;
import com.ez.DbConnection;
import com.ez.DbConnectionFactory;
/**
* @author 窗外赏雪(EZ编程网)
*/
public class FactoryTest {
public static void main(String[] args) throws Exception {
DbConnectionFactory factory=new SimpleDbConnectionFactory();
//注入简单工厂
DbUnit dbUnit=new DbUnit(factory);
DbConnection connection = dbUnit.getConnection("mysql");
connection = dbUnit.getConnection("oracle");
connection = dbUnit.getConnection("db2");
System.out.println("==============================");
factory=new ComplexDbConnectionFactory();
dbUnit=new DbUnit(factory);
connection = dbUnit.getConnection("mysql");
connection = dbUnit.getConnection("oracle");
connection = dbUnit.getConnection("db2");
System.out.println("==============================");
}
}
package com.ez.biz;
import com.ez.DbConnection;
import com.ez.DbConnectionFactory;
/**
* 获取数据库连接
* @author 窗外赏雪(EZ编程网)
*/
public class DbUnit {
DbConnectionFactory factory;
public DbUnit(DbConnectionFactory factory) {
this.factory=factory;
}
public DbConnection getConnection(String type){
DbConnection dbConnection;
//通过传入数据库类型,使用工厂创建对应数据库的连接
dbConnection=factory.createDbConnection(type);
dbConnection.init();
dbConnection.prepare();
dbConnection.connect();
return dbConnection;
}
}
package com.ez;
public abstract class DbConnectionFactory {
public abstract DbConnection createDbConnection(String type);
}
package com.ez.biz;
import com.ez.DbConnection;
import com.ez.DbConnectionFactory;
import com.ez.impl.ComplexDb2Connection;
import com.ez.impl.ComplexMySqlConnection;
import com.ez.impl.ComplexOracleConnection;
/**
* 具体工厂
* @author 窗外赏雪(EZ编程网)
*/
public class ComplexDbConnectionFactory extends DbConnectionFactory{
@Override
public DbConnection createDbConnection(String type) {
DbConnection dbConnection=null;
if("mysql".equals(type)){
dbConnection=new ComplexMySqlConnection();
}else if("oracle".equals(type)){
dbConnection=new ComplexOracleConnection();
}else if("db2".equals(type)){
dbConnection=new ComplexDb2Connection();
}
return dbConnection;
}
}
package com.ez.biz;
import com.ez.DbConnection;
import com.ez.DbConnectionFactory;
import com.ez.impl.Db2Connection;
import com.ez.impl.MySqlConnection;
import com.ez.impl.OracleConnection;
/**
* 创建数据库连接的工厂类
* @author 窗外赏雪(EZ编程网)
*/
public class SimpleDbConnectionFactory extends DbConnectionFactory{
public DbConnection createDbConnection(String type){
DbConnection dbConnection=null;
if("mysql".equals(type)){
dbConnection=new MySqlConnection();
}else if("oracle".equals(type)){
dbConnection=new OracleConnection();
}else if("db2".equals(type)){
dbConnection=new Db2Connection();
}
return dbConnection;
}
}