综合使用抽象工厂、工厂方法的应用

03-04-18 manbaum

假设有一个应用,需要对数据库进行操作。虽然操作的表是一样的,但是,不同的用户连接的库可能不同,还可能不同的数据库存在于不同的数据库系统上。如何来实现呢?综合抽象工厂、工厂方法的使用,我们得到以下解决方法。

/*
 * 抽象工厂,定义对数据库的各种操作。
 */
public Interface Operations
{
    public int operation1();
    public void operation2(String paramString1);
    // ... 其他操作 ...
}

/*
 * 工厂方法,根据不同数据库系统及数据库,建立操作工厂。
 */
public class OperationsFactory
{
    public static final int DBMS_MYSQL = 1;
    public static final int DBMS_MSSQL = 2;
    public static final int DBMS_ORACLE = 3;

    // 工具类,禁止实例化
    private OperationsFactory()
    {
    }

    public static Operations getOperations(int dbms, String dbName)
    {
        Operations op;
        switch (dbms)
        {
            case DBMS_MYSQL:
                // ... 获得 MySQL 数据库实现 ...
                op = new MysqlOperations(dbName);
                break;
            case DBMS_MSSQL:
                // ... 获得 Microsoft SQL Server 数据库实现 ...
                op = new MssqlOperations(dbName);
                break;
            case DBMS_ORACLE:
                // ... 获得 Oracle 数据库实现 ...
                op = new OracleOperations(dbName);
                break;
            default:
                throw new Exception("Unsupported dbms: " + dbms);
        }
        return op;
    }
}

/*
 * 抽象工厂的具体实现,针对 MySQL 数据库系统。
 * 类似的可以有针对 M$ SQL Server 及 Oracle 的具体实现。
 */
public class MysqlOperations implements Operations
{
    private Connection conn;

    public MysqlOperations(String dbName)
    {
        // ... 根据 dbName 生成连接
        conn = ...
    }
 
   // ... 实现接口方法 operation1 ...
   public int operation1()
   {
       // 使用 conn 对数据库进行操作 ...
   }

   // ... 实现接口方法 operation2 ...
   public void operation2(String paramString1)
   {
       // 使用 conn 对数据库进行操作 ...
   }
}
<p class="indent">


这样,用户无须知道它连接的具体数据库系统以及数据库名,就可以执行他需要的操作(使用抽象工厂接口),完成他自身的任务。具体使用何数据库系统上的哪个库,在用户登录后,由管理者指定(使用工厂方法工具类)。

banq
2003-04-28 16:39
好,不错,鼓掌......

bruce
2003-06-11 09:08
抽象产品在哪里?是不是Connection ? 好象又不象,似乎没有吧?
如果没有的话,我认为就不是一般的抽象工厂方法了,因为它的两个首要因素就是抽象产品,抽象工厂.并且所有的具体工厂类都要返回抽象产品,我倒不是死扣定义,只是觉得长得不和一般的抽象工厂一样罢了。

airport
2003-06-11 14:23
说几点看法,请多指教
关于你的抽象工厂 Interface Operations
我觉得本身定义太具体化了,违反面向对象的原则
因为你对数据库的操作,本身是一个具体的过程
定义在抽象工厂里面,我想如果以后扩展起来肯定很麻烦
所以不同数据库的操作,还是不适合用这个模式吧,应该是
bridge模式吧。

bruce
2003-06-11 20:19
我倒不觉得Interface Operations定义的太具体化,因为具不具体或抽不抽象取决于定义的方法operate1, operate2抽象程度。

感觉上面的代码只能称做工厂方法模式,根本没有抽象工厂模式。

呵呵,看到bridge模式,我就想起来斑主给咱们的加奶的咖啡,收益非浅呀。

richardluopeng
2003-06-16 10:45
请楼主告诉我

客户端是怎么调用的,谢谢!

eastxing
2003-06-16 16:16
客户端的调用就很简单了:
Operations mysqlop = OperationsFactory.getOperations(MYSQL,"tt");
mysqlop.operation1();
mysqlop.operation2();
……

感觉就是用的工厂方法,由“数据库类型”和“数据库名”生成操作对象。如果再掩藏“数据库类型”,建立工厂这边的类结构(例如建立一个共同的数据库的基类,按数据库类型建立不同的工厂),那就是抽象工厂了。不过我觉得也没有必要,楼主的实现已经不错了,支持!

richardluopeng
2003-06-17 09:20
抽象工厂在哪里??

Lijm
2003-06-17 09:52
一点看法,
这种方式象是一个共同的函数而已,并没有体现出抽象工厂的思想。
如果这个模块要拓展,该怎么呢?比如说是增加一种数据库,是不是要更改代码了,没有体现“关--闭”原则。

a_fan_ti
2003-06-18 13:09
我觉得这是一个简单工厂

richardluopeng
2003-06-18 18:39
我仔细看了一下,抽象工厂和一个简单工厂的应用

richardluopeng
2003-06-18 18:41
我认为


public static Operations getOperations(int dbms, String dbName)
{
}

是一个简单工厂,不是工厂方法

Fish
2003-07-25 09:40
yes!! 这就是一个简单工厂。 非常典型的一个简单工厂。楼主除了把它认为是抽象工厂这个错误外,其它做的都非常好。

更正一下:

> 就可以执行他需要的操作(使用抽象工厂接口),完成他自身的任务

这里好像应该是

就可以执行他需要的操作(使用抽象产品接口),完成他自身的任务

大家认为呢?

ruby
2003-07-25 10:17
是一个Simple Factory的应用,写的例子和阎宏的《java与模式》中提到的水果家场例子是一样的。就是由一个工厂类可以根据传入的参量决定创建出哪一种产品类的实例.

ruby
2003-07-25 10:24
to manbaum
请教一下,你程序中的
// 工具类,禁止实例化
private OperationsFactory()
{
}
这儿为什么要禁止实例化?如果可以实例化,会带来什么后果?

2Go 1 2 下一页