抽象工廠模式

定義:提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類

通常是在運行時刻再創建一個concreteFactory類的實例,這個具體工廠再創建具有特定實現的產品對象,也就是說,爲創建不同的產品對象,客戶端應使用不同的具體工廠
所有在用簡單工廠的地方,都可以考慮用反射技術來去除switchif,解除分支判斷帶來的耦合
反射技術可以將簡單工廠中的判斷去除,進一步解放代碼。

先看個例子,慢慢解釋

先是一個用戶表,可能會存在多個字段,這裏只用id 與name 示例

class User
{
    private int id;
    private String name;
    // getter && setter
}

用戶表可能的操作,這裏只示意插入與查詢


public interface IUser
{
    void insert(User user);
    User getUser(int id);
}

另外一個表,同用戶表,這裏用部門表示例做區分,用以擴展業務

public class Department
{
    private String name;
    // getter && setter
}

部門表的不同操作

public interface IDepartment
{
    void insert(Department department);
    Department getDepartment(String name);
}

定義不同數據庫操作方法的接口

interface IFactory
{
    IUser createUser();
}

具體數據庫連接 SQLServer

class SqlServerFactory implements IFactory
{
    public IUser createUser()
    {
        return new SqlServerUser();
    }
}

具體數據庫連接 Access

class AccessFactory implements IFactory
{
    public IUser createUser()
    {
        return new Accessuser();
    }
}

SqlServer 用戶操作實現方法

class SqlServerUser implements IUser
{
    public void insert(User user)
    {
        System.out.println("sql server insert user");
    }

    public User getUser(int id)
    {
        System.out.println("get user from sql server");
        return null;
    }
}

SqlServer 部門表的操作實現方法

public class SqlServerDepartment implements IDepartment
{
    public void insert(Department department)
    {
        System.out.println("insert department to sqlserver");
    }
    public Department getDepartment(String name)
    {
        System.out.println("get department from sqlserver");
        return null;
    }
}

Access 用戶操作方法

class Accessuser implements IUser
{
    public void insert(User user)
    {
        System.out.println("access insert user");
    }
    public User getUser(int id)
    {
        System.out.println("get user from access");
        return null;
    }
}

Access 部門表的操作方法

public class AccessDepartment implements IDepartment
{

    public void insert(Department department)
    {
        System.out.println("insert into access a department");
    }

    public Department getDepartment(String name)
    {
        System.out.println("get a department from access");
        return null;
    }

}

管理所有數據庫連接的獲取,這裏用了兩個方式

  1. switch 關鍵詞直接判斷,可用
  2. 利用反射技術,此示例代碼會拋出異常,因爲配置的類的全路徑需要修改,項目中是需要使用配置文件的,也就不會有此問題
public class DataAccess
{
    private static db d = db.SqlServer;

    public static IUser createUser()
    {
        IUser result = null;
        try
        {
            result = (IUser) Class.forName(d.toString()).newInstance();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        if (result != null)
        {
            return result;
        }
        switch (d)
        {
        case SqlServer:
            result = new SqlServerUser();
            break;
        case Access:
            result = new Accessuser();
            break;
        default:
            break;
        }
        return result;
    }

    public static IDepartment createDepartment()
    {
        IDepartment result = null;
        try
        {
            result = (IDepartment) Class.forName(d.toString()).newInstance();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        if (result != null)
        {
            return result;
        }
        switch (d)
        {
        case SqlServer:
            result = new SqlServerDepartment();
            break;
        case Access:
            result = new AccessDepartment();
            break;
        default:
            break;
        }
        return result;

    }
}

enum db
{
    SqlServer, Access
}

客戶端代碼就比較簡單了,此模式要實現的目的就是讓客戶端成爲傻逼,只要做事就可以了,其他的由配置完成,客戶端調用時完全無感,這樣如果增加新的數據庫,只要實現IFactory接口獲取連接、實現IUser獲取對用戶表的操作、實現IDepartment 獲取對部門表的操作就可以。
沒辦法,改換數據庫是個大工程,必須要有修改,我們要實現的目的就是將修改減至最少

public class AbstractFactoryMain
{
    public static void main(String[] args)
    {
        User user = new User();
        Department dept = new Department();

        IUser iu = DataAccess.createUser();
        iu.insert(user);
        iu.getUser(1);

        IDepartment department = DataAccess.createDepartment();
        department.insert(dept);
        department.getDepartment("le");
    }
}

總結:此模式名爲抽象工廠,區別與前面的工廠模式的就是這裏的工廠方法也是抽象的,可以有多個不同的具體工廠

發佈了106 篇原創文章 · 獲贊 49 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章