博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从简单工厂到工厂方法
阅读量:5916 次
发布时间:2019-06-19

本文共 3826 字,大约阅读时间需要 12 分钟。

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

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的配置文件那样。

转载地址:http://cfgpx.baihongyu.com/

你可能感兴趣的文章
四则运算
查看>>
Qt5 for Android: incompatible ABI
查看>>
zookeeper学习
查看>>
class类名的管理
查看>>
LeetCode:Rectangle Area
查看>>
文本查询
查看>>
查看帐号授权信息
查看>>
小程序(四):模板
查看>>
【转】Java - printf
查看>>
jquery获取元素到屏幕底的可视距离
查看>>
ENDNOTE使用方法(转发)
查看>>
计算机数制和运算的一点总结.
查看>>
UML系列 (五) 为什么要用UML建模之建模的重要性
查看>>
框架是什么,框架有什么用(转)
查看>>
集成测试
查看>>
c3p0连接池配置
查看>>
对于I/O流中解压中遇到的问题
查看>>
问答项目---用户注册的那些事儿(JS验证)
查看>>
Android进阶篇-百度地图获取地理信息
查看>>
返回前一页并刷新页面方法
查看>>