• 从简单工厂到工厂方法


    本例子背景为根据客户端不同的选择,生成不同的数据库连接

    0. 无工厂代码

    package nofactory;
    
    public class NoFactory {
        private static final short MYSQL = 0;
        private static final short SQLSERVER = 1;
    
        public static void connect(short dbType) {
            switch (dbType) {
                case MYSQL:
                    System.out.println("MySQL connected");
                    break;
                case SQLSERVER:
                    System.out.println("SQLServer connected");
                    break;
                default:
                    System.out.println("Unknown database type");
            }
        }
    
        public static void main(String[] args) {
            connect(MYSQL);
        }
    }

    这种写法的坏处在于客户端代码和产品代码(数据库)紧耦合,每次需求修改(例如添加数据库,更改数据库表现方式等等)需要对整个代码进行改动。

    1. 使用工厂,先看如下3个固定的产品类

    DataBase.java

    package db;
    
    public abstract class DataBase {
        public static final short MYSQL = 0;
        public static final short SQLSERVER = 1;
        public static final String MYSQL_CLASSNAME = "db.MySQL";
        public static final String SQLSERVER_CLASSNAME = "db.SQLServer";
        public abstract void connect();
    }

    MySQL.java

    package db;
    
    public class MySQL extends DataBase {
        @Override
        public void connect() {
            System.out.println("MySQL connected");
        }
    }

    SQLServer.java

    package db;
    
    public class SQLServer extends DataBase {
        @Override
        public void connect() {
            System.out.println("SQLServer connected");
        }
    }

    1.1 简单工厂

    package simplefactory;
    
    import db.DataBase;
    import db.MySQL;
    import db.SQLServer;
    
    public class DBFactory {
        private DBFactory() {}
    
        public static DataBase createDataBase(short dbType) {
            switch (dbType) {
                case DataBase.MYSQL:
                    return new MySQL();
                case DataBase.SQLSERVER:
                    return new SQLServer();
                default:
                    return null;
            }
        }
    }

    客户端

    package simplefactory;
    
    import db.DataBase;
    
    public class Test {
        public static void main(String[] args) {
            DataBase db = DBFactory.createDataBase(DataBase.MYSQL);
            db.connect();
        }
    }

    简单工厂的好处在于将客户端和产品分离,使得要生成不同的数据库链接只需要修改客户端就可以

    缺点在于产品工厂的生产全在一起(耦合),如果添加了产品需要修改switch语句,从而会影响到其他产品

    1.2 工厂方法

    DBFactory.java

    package factorymethod;
    
    import db.DataBase;
    
    public class DBFactory {
        protected DBFactory() {}
        protected static DataBase createDB() { return null; }
    }

    MySQLFactory.java

    package factorymethod;
    
    import db.DataBase;
    import db.MySQL;
    
    public class MySQLFactory extends DBFactory{
        private MySQLFactory() {}
    
        public static DataBase createDB() {
            return new MySQL();
        }
    }

    SQLServerFactory.java

    package factorymethod;
    
    import db.DataBase;
    import db.SQLServer;
    
    public class SQLServerFactory extends DBFactory{
        private SQLServerFactory() {}
    
        public static DataBase createDB() {
            return new SQLServer();
        }
    }

     

    客户端

    package factorymethod;
    
    import db.DataBase;
    
    public class Test {
        public static void main(String[] args) {
            DataBase db = SQLServerFactory.createDB();
            db.connect();
        }
    }


    工厂方法的目的在于消除简单工厂里的 switch , 达到添加和修改产品类的时候产品之间互相解耦,另外要特别注意工厂父类的protected的使用,他可以防止客户端直接创造父类工厂(因为一般来说客户端和工厂类不会在同一个包里)。

    其实我Y就一直明白这TM漫天遍地都是用这个形式的例子来介绍工厂方法,这个例子就是个悲剧。我就问了,你Y在客户端直接new和你用这一大堆工厂有何区别,如下:

    public static void main(String[] args) {
        DataBase db = new MySQL();
        db.connect();
    }

    这和你上面的工厂方法有何区别,还省去了一大堆的工厂

    1.3  。。。

    ABFactory.java

    package abstractfactory;
    
    import db.DataBase;
    
    public class ABFactory {
        private ABFactory() {}
    
        public static DataBase createDB(String dbName) {
            try {
                return (DataBase) Class.forName(dbName).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    客户端

    package abstractfactory;
    
    import db.DataBase;
    
    public class Test {
        public static void main(String[] args) {
            DataBase db = ABFactory.createDB(DataBase.MYSQL_CLASSNAME);
            db.connect();
        }
    }

    他的优点就显而易见了,即使你怎么添加产品类和修改产品类,也不需要去修改工厂,而且和客户端彻底解耦,一般来讲我们可以将数据库的类名放在XML配置文件里,工厂方法去读取他就可以了,就像Spring的配置文件那样。

  • 相关阅读:
    将迁移学习用于文本分类 《 Universal Language Model Fine-tuning for Text Classification》
    深度 | 提升深度学习模型的表现,你需要这20个技巧(附论文)
    [线性代数] 矩阵白化
    基于搜索的贝叶斯网络结构学习算法-K2
    Deep learning:四十三(用Hessian Free方法训练Deep Network)
    2020年AI、CV、NLP顶会最全时间表
    浅谈人脸识别中的loss 损失函数
    控制uniFrame显示的一个管理类
    php+sqlserver之如何操作sqlserver数据库
    php支持连接sqlserver数据库
  • 原文地址:https://www.cnblogs.com/zemliu/p/2750583.html
Copyright © 2020-2023  润新知