设计模式 抽象工厂模式

171 阅读3分钟

抽象工厂:

定义与类型

  • 定义:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口
  • 无需制定它们具体的类
  • 类型:创建型 使用场景
  • 客户端不依赖于产品类实例如何被创建、实现等细节
  • 强调一系列相关的产品对象(属于统一产品族)一起使用创建对象需要大量重复的代码
  • 提供一个产品类的库,所以的产品以同样的接口出现,从而使客户端不依赖具体实现 优点
  • 具体产品在应用层代码隔离,无须关系创建细节
  • 将一个系列的产品统一到一起创建 缺点
  • 规定了所有可能被创建的产品集合,产品族扩展新的产品困难,需要修改抽象工厂的接口
  • 增加了系统的抽象性和理解难度

UML关系图:

Abstract-Factory.png
抽象工厂主要分为4类:

  • AbstractFactory:抽象工厂角色,它声明了一组用于创建一种产品的方法,每一个方法对应一种产品,如上述类图中的AbstractFactory就定义了两个方法,分别创建产品A和产品B
  • ConcreteFactory:具体工厂角色,它实现了在抽象工厂中定义的创建产品的方法,生产一组具体产品,这饿产品构件成了一个产品种类,每一个产品都位于某个产品等级结构中,如上述类图中的ConcreteFactoryA和ConcreteFactoryB
  • AbstractProduct:抽象产品角色,为每种产品声明接口,如图中AbstractProductA、AbstractProductB
  • ConcreteProduct:具体产品角色,定义了工厂生产的具体产品对象,实现抽象产品接口声明的业务方法,如图中ConcreteProductA1、ConcreteProductA2、ConcreteProductB1、ConcreteProductB2

模式代码

  • AbstractProduct:
public abstract class Video {
    public abstract void produce();
}
  • ConcreteProduct:
public class PythonVideo extends Video {
    @Override
    public void produce() {
        System.out.println("Python课程视频");
    }
}
public class JavaVideo extends Video {
    @Override
    public void produce() {
        System.out.println("录制Java课程视频");
    }
}
  • AbstractFactory:
public interface CourseFactory {
    Video getVideo();
    Article getArticle();

}
  • ConcreteFactory:
public class JavaCourseFactory implements CourseFactory {
    @Override
    public Video getVideo() {
        return new JavaVideo();
    }

    @Override
    public Article getArticle() {
        return new JavaArticle();
    }
}
public class PythonCourseFactory implements CourseFactory {
    @Override
    public Video getVideo() {
        return new PythonVideo();
    }

    @Override
    public Article getArticle() {
        return new PythonArticle();
    }
}

源码中的使用:

  • java.sql下的Statement、CallableStatement(抽象产品):
public interface Statement extends Wrapper, AutoCloseable {
    '省略代码'
}
public interface CallableStatement extends PreparedStatement {
    '省略代码'
}
  • com.mysql.jdb下的StatementImpl、CallableStatement(具体产品)
public class StatementImpl implements Statement {
   '省略代码'
}
package com.mysql.jdbc;
public class CallableStatement extends PreparedStatement implements java.sql.CallableStatement {
   '省略代码'
}
  • java.sql下的Connection(抽象工厂):
public interface Connection  extends Wrapper, AutoCloseable {

    Statement createStatement() throws SQLException;

    CallableStatement prepareCall(String sql) throws SQLException;
    '省略代码'
  • com.mysql.jdbc下的ConnectionImpl(具体工厂):
public class ConnectionImpl extends ConnectionPropertiesImpl implements Connection {
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
        this.checkClosed();
        StatementImpl stmt = new StatementImpl(this, this.database);
        stmt.setResultSetType(resultSetType);
        stmt.setResultSetConcurrency(resultSetConcurrency);
        return stmt;
    }
   public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        if (this.versionMeetsMinimum(5, 0, 0)) {
            CallableStatement cStmt = null;
            if (!this.getCacheCallableStatements()) {
                cStmt = this.parseCallableStatement(sql);
            } else {
                LRUCache var5 = this.parsedCallableStatementCache;
                synchronized(this.parsedCallableStatementCache) {
                    ConnectionImpl.CompoundCacheKey key = new ConnectionImpl.CompoundCacheKey(this.getCatalog(), sql);
                    CallableStatementParamInfo cachedParamInfo = (CallableStatementParamInfo)this.parsedCallableStatementCache.get(key);
                    if (cachedParamInfo != null) {
                        cStmt = CallableStatement.getInstance(this, cachedParamInfo);
                    } else {
                        cStmt = this.parseCallableStatement(sql);
                        cachedParamInfo = cStmt.paramInfo;
                        this.parsedCallableStatementCache.put(key, cachedParamInfo);
                    }
                }
            }

            cStmt.setResultSetType(resultSetType);
            cStmt.setResultSetConcurrency(resultSetConcurrency);
            return cStmt;
        } else {
            throw SQLError.createSQLException("Callable statements not supported.", "S1C00");
        }
    }
}

抽象工厂在实际的开发中运用并不多,主要是在开发工程中很少会出现多个产品种类的情况,大部分情况使用工程模式即可解决