简单工厂模式
工厂模式作为创建型模式的一种,它首先将需要生产的产品抽象化,提取出一个公共的接口,而每一个产品就是这个接口的实现类。然后创建一个工厂类,当我们工厂类生产产品时,只需要返回该接口即可。
此处参考该博客
简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一
优点:
在于工厂类中包含了必要的逻辑,根据客户需要的条件动态实例化相关的类,对客户端来说,去掉了与具体产品的依赖。
缺点:
工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,当增加新的东东时,会违反开放-封闭原则
实现
已知三种数据库,MySQL、Oracle、SQLServer,现在有一个项目,该项目并不确定使用哪种数据库,此时我们通过工厂模式,工厂提供一个公共的接口提供给项目进行数据库连接,而具体的连接实现隐藏。
产品接口-数据库连接接口
public interface DBConnect {
/**
* 数据库连接方法
* @return void
* 时间:2018年4月24日
*/
public void connect();
}
具体产品-三种数据库连接
public class MySQLConnect implements DBConnect{
@Override
public void connect() {
System.out.println("Mysql Connect");
}
}
public class OracleConnect implements DBConnect{
@Override
public void connect() {
System.out.println("Oracle Connect");
}
}
public class SQLServerConnect implements DBConnect{
@Override
public void connect() {
System.out.println("SQLServer Connect");
}
}
工厂类-数据库连接工厂
public class ConnectFactory {
public static DBConnect getConnect(String type) {
if (null == type || 0 == type.length()) {
return null;
}
if ("mysql".equalsIgnoreCase(type)) {
return new MySQLConnect();
}
if ("oracle".equalsIgnoreCase(type)) {
return new OracleConnect();
}
if ("sqlserver".equalsIgnoreCase(type)) {
return new SQLServerConnect();
}
return null;
}
}
客户类
public class FactoryPatternDemo {
public static void main(String[] args) {
ConnectFactory connectFactory = new ConnectFactory();
DBConnect dbConnect = connectFactory.getConnect("mysql");
dbConnect.connect();
}
}
此时,若我们又需要连接Access数据库,就需要对工厂类进行修改,这违反了开闭原则。
工厂方法模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
四个要素
- 工厂接口:工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。在实际编程中,有时候也会使用一个抽象类来作为与调用者交互的接口,其本质上是一样的。
- 工厂实现:在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就需要有多少个具体的工厂实现。
- 产品接口:产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则。
- 产品实现:实现产品接口的具体类,决定了产品在客户端中的具体行为。
优点
创建对象的接口,让子类去决定具体实例化的对象,把简单的内部逻辑判断移到了客户端代码。工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。
实现
我们依然拿上一个数据库连接的案例来说明。
产品接口
public interface DBConnect {
/**
* 数据库连接方法
* @return void
* 时间:2018年4月24日
*/
public void getConnect();
}
具体产品
public class MySQLConnect implements DBConnect{
@Override
public void getConnect() {
System.out.println("MysqlConnect");
}
}
public class SQLServerConnect implements DBConnect{
@Override
public void getConnect() {
System.out.println("SQLServer Connect");
}
}
public class OracleConnect implements DBConnect{
@Override
public void getConnect() {
System.out.println("Oracle Connect");
}
}
工厂接口
public interface ConnectFactory {
/**
* 返回数据库连接对象
* @return DBConnect
* @return
* 时间:2018年4月24日
*/
public DBConnect getDBConnect();
}
具体工厂-MySQL工厂
public class MySQLConFactory implements ConnectFactory{
@Override
public DBConnect getDBConnect() {
return new MySQLConnect();
}
}
客户类
public class FactoryMethodPatternDemo {
public static void main(String[] args) {
DBConnect connect = new MySQLConFactory().getDBConnect();
connect.getConnect();
}
}
从这里我们可以看出,工厂方法模式相对于简单工厂模式的区别
- 简单工厂模式只是将产品抽象化,创建了一个产品的公共接口,而对于工厂是一个具体实现。当我们需要添加新的产品时,除了添加该产品的实现类,同时也要对这具体的工厂类进行修改,在if中增加相应的判断
- 工厂方法模式相对于简单工厂就高明了一步,它不仅将产品抽象化,同时也将工厂抽象出来。
- 工厂方法模式与简单工厂模式的产品接口及其实现可以说目的是相同的,可以看成一样,在上方案例代码有所体现
- 但是工厂方法模式将工厂抽象化,它提供了一个工厂接口,这个工厂接口只提供一个创建产品接口的方法。具体生成哪一个产品,则由该工厂接口的实现类来决定。
- 这样当我们需要添加一个新的Access数据库时,只需要创建相应的产品实现类以及工厂实现类即可,满足了开闭原则