工厂模式
程序员文章站
2022-07-14 08:55:21
...
当我们获取数据库连接(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; } }
下一篇: JFinal的五个抽象方法