Design Pattern Series III: Abstract Factory mode __ design mode

Source: Internet
Author: User
Tags reflection

Preface

There are three patterns in the design pattern that are related to the factory pattern: The Simple factory model, the factory method pattern, and the abstract factory pattern. In the previous article has talked about the first two kinds, here on the abstract factory model. Abstract Factory mode is to provide a set of interrelated or interdependent interfaces (that is, abstract classes) without specifying a specific class. In short, when we need to create a specific object, we do not have to specify the object, just use its upper-layer interface to call directly on the line. It seems to be very abstract oh, well, in order to understand this design pattern more clearly, we still use a case to illustrate
Problem Background

A company has developed a software that uses SQL Server for the database. Since the customer required the use of Oracle database, the original data to migrate to Oracle, in the process of migration encountered many problems, such as syntax errors, keyword abuse, function does not support and so on. Please design a set of programs to achieve seamless data migration. Brief Introduction

By using our factory method model, we have better solve the problem that users use different databases, now we have obtained the database object to create, then we need to add the data to the database, assuming all need to add department information, some users need to use Oracle, Some users need to use SQL Server. Consider the code structure of the abstract factory pattern:

Abstract Factory Pattern Implementation

Before modifying the code structure, for a better comparison, look at our current code structure:

prior to modification (based on abstract Factory mode)

Raw Code v1.0:

    Public interface Ifactory {//CREATE database Object DBObject createdbobject ();
    Create department idepartment Createdepartment ();  public class Oraclefactory implements ifactory{@Override public dbobject createdbobject () {return
    New Oracleobject ();
    @Override public idepartment createdepartment () {return new oracledepartment ();
        } public class Sqlserverfactory implements ifactory{@Override public dbobject createdbobject () {
    return new SQLSERVEROBEJCT ();
    @Override public idepartment createdepartment () {return new sqlserverdepartment ();

    The public abstract class DBObject {//Add user's method public abstract void Insertuser (user user);
    Methods to find user information public abstract user Finduserbyid (int id); public class Oracleobject extends dbobject{@Override public void insertuser (user user) {System.ou
    T.println ("Add User with Oracle"); @Override Public USer Finduserbyid (int id) {SYSTEM.OUT.PRINTLN ("Use Oracle to find user by id");
    return null;
        } public class Sqlserverobejct extends dbobject{@Override public void insertuser (user user) {
    System.out.println ("Add Users using SQL Server");
        @Override Public user Finduserbyid (int id) {SYSTEM.OUT.PRINTLN ("Use SQL Server to find users by id");
    return null;
    } public interface Idepartment {//Create Department void Insertdept (Department dept);
    Find Department Department finddeptbyid (int id);
        public class Oracledepartment implements idepartment {@Override public void insertdept (Department dept) {
    System.out.println ("Insert a departmental information using an Oracle object"); 
        @Override public Department Finddeptbyid (int id) {SYSTEM.OUT.PRINTLN ("Use the Oracle object to find the departmental information with ID + ID +");
    return null;  The public class Sqlserverdepartment implements idepartment {@Override public void insertdept (Department
    Dept) {    System.out.println ("Add a Department information using SQL Server object"); @Override public Department Finddeptbyid (int id) {SYSTEM.OUT.PRINTLN ("Use SQL Server object to find department information with ID + ID +"
        ");
    return null;
        }///test method public static void main (string[] args) {Ifactory factory = new Oraclefactory ();

        Ifactory Factory2 = new Sqlserverfactory ();
        Idepartment Department = factory.createdepartment ();

        Idepartment Department2 = Factory2.createdepartment ();
        Department.insertdept (dept);
        Department.finddeptbyid (1);
        Department2.insertdept (dept);        
    Department2.finddeptbyid (2); }
first modification (based on simple Factory mode)

According to the abstract factory pattern structure diagram and requirements, modify the code as follows:
1 Add an abstract factory that creates a department, where interfaces are used
2 Create an Oracle based and SQL Server based departmental implementation class (already implemented in the code above)
3 Create a Database tool class that creates the objects you want according to the criteria
Modified Code v1.1

    public class DBAccess {//Here fixed the value of DBTYPE, if you want to use another database, modify the value of this field is good private static final String DBTYPE = "Oracle";  public static DBObject Createdbobject () {switch (DBTYPE) {case ' Oracle ': return new
            Oracleobject ();
        Case "SQL Server": return new Sqlserverobejct ();
    return null; public static Idepartment createdepartment () {switch (DBTYPE) {case ' Oracle ': return n
        EW oracledepartment ();
        Case "SQL Server": return new Sqlserverdepartment ();
    return null;
        }///test method public static void main (string[] args) {User user = new user ();

        Department Dept = new Department ();
        The dbobject created here is the database object DbType the value specified above dbobject dbobject = Dbaccess.createdbobject ();
        Dbobject.insertuser (user);

        Dbobject.finduserbyid (1);
    Idepartment Department = dbaccess.createdepartment ();    Department.insertdept (dept);
    Department.finddeptbyid (1); }

Here through the Dbaccess class directly replaced the original ifactory, Oraclefactory, sqlserverfactory three classes, here is actually a simple factory implementation method, the logic of the judgment transferred to the dbaccess, the client does not need to make any changes, To replace the database, you only need to modify the DbType value in the dbaccess to OK. At this point, it seems that a simple factory is dominant, but not necessarily, if you want to add support for the MySQL database in your program, use the original abstract factory pattern. Just add a mysqlfactory class, and now you need to modify the logical judgment in the Dbaccess class (which violates the closed open principle). So is there a way to not increase the decision on the switch to create the corresponding object based on the value of the DbType? That is, an instance of the class is created based on the string representation of the class while the program is running. The answer is yes, in Java we can use reflection technology to do this, so we make further changes to the v1.1 version of the code: Second modification (based on reflection technology)

v1.2

    public class DBAccess {
        private static final String DBTYPE = "Oracle";
        public static DBObject Createdbobject () throws ClassNotFoundException, Instantiationexception, illegalaccessexception {return
            (dbobject) class.forname ("Com.rhwayfun.GoF." + DBTYPE + "Object"). newinstance ();

        public static Idepartment Createdepartment () throws Instantiationexception, Illegalaccessexception, classnotfoundexception{return
            (idepartment) class.forname ("Com.rhwayfun.GoF." + DBTYPE + "Department"). Newinstance ();
        }
    

Now, if you need to increase the support for MySQL only need to modify Oracle for MySQL on the line, but still have to create the Mysqlobject class and Mysqldepartment class, but with the above simple factory model changes, here is only in the original code on the basis of the increase, is extended rather than modified. So there is no breach of the open-closed principle, now this version of the code is much better than before, but the value of DbType is still inevitable to be modified, in fact, there is a way through the configuration file can save the original code to achieve this function, the following code for the third time modified: Third modification (based on configuration file + reflection technology)

First create db.properties configuration file

    Dbtype=oracle

v1.3 Version Code

public class DBAccess {public
        static DBObject Createdbobject () throws ClassNotFoundException, Instantiationexception, Illegalaccessexception, ioexception{return
            (dbobject) class.forname ("Com.rhwayfun.GoF . "+ Readpro () +" Object "). newinstance ();

        public static Idepartment Createdepartment () throws Instantiationexception, Illegalaccessexception, ClassNotFoundException, ioexception{return
            (idepartment) class.forname ("Com.rhwayfun.GoF." + readpro () + " Department "). newinstance ();

        private static String Readpro () throws ioexception{
            Properties Pro = new properties ();
            InputStream in = DBAccess.class.getClassLoader (). getResourceAsStream ("Com/rhwayfun/gof/db.properties");
            Pro.load (in);
            Return (String) pro.get ("DBTYPE");
        }
    

The client code remains unchanged and the actual test is successful. Summary of abstract factory patterns

From v1.0 to v1.3 we make a simple summary of the factory model: all the simple factories can consider using reflection technology to optimize the abstract factory the biggest benefit is to facilitate the exchange of product lines, to create different products, we can use different factories to create. So when we need products of different product lines, we just need to change a factory. Abstract Factory mode and factory method model to separate the process of creating an instance from the client, the user operates only abstract interfaces, and the specific creation process is encapsulated in a specific factory to achieve. A good embodiment of the open-closed principle there is a drawback between abstract Factory mode and abstract factory pattern, that is, there are many classes to be created when new features need to be added. Simple factory model can overcome the appeal by reflection technology, but using reflection can reduce the performance of the program, so although the use of reverse to avoid creating multiple classes of trouble, but also reduce the performance of the program, the so-called gain must be lost. It needs to be carefully measured in real-world development.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.