设计模式-抽象工厂模式

抽象工厂

1.定义与类型

  • 抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类
  • 创建型

2.适用场景

  • 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
  • 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量的重复代码
  • 提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现

3.优点

  • 具体产品在应用层的代码隔离,无需关心创建的细节
  • 将一个系列的产品统一到一起创建

4.缺点

  • 规定了所有可能被创建的产品集合,产品簇中扩展新的产品困难;
  • 增加了系统的抽象性和理解难度

5.Coding

​ 编码之前我们先明确一个概念:比如一个车厂,他可能做汽车,电动车,自行车。对于下面一些列的附属产品,又分别设立了汽车厂,电动车厂,自行车厂...

​ 在这个例子中整个车厂便是一个抽象工厂,其下面附属的厂便是一个又一个具体工厂。如果把车场整体当做一个抽象类,那么具体的工厂就是这个抽象类的实现。

  • 课程文章接口
public abstract class Article {
    public abstract void produce();
}
  • JAVA课程文章
public class JavaArticle extends Article{
    @Override
    public void produce() {
        System.out.println("正在创建java文章");
    }
}
  • Python课程文章
public class PythonArticle extends Article{
    @Override
    public void produce() {
        System.out.println("正在准备Python文章...");
    }
}
  • 课程视频接口
public abstract class Video {
   public  abstract void produce();
}
  • JAVA课程视频
public class JavaVideo extends Video{

    @Override
    public void produce() {
        System.out.println("正在录制java视频....");
    }
}
  • Python课程视频
public class PythonVideo extends  Video{
    @Override
    public void produce() {
        System.out.println("正在录制python视频...");
    }
}

上述是JAVA工厂和Python工厂每个工厂下的两种产品。

我们可以定义抽象工厂来指定工厂的实现

  • 创建抽象工厂
public interface AbstractCourseFactory {
        Video getCourse();
        Article getArticle();
}
  • JAVA工厂
public class JavaCourseFactory implements CourseFactory{
    @Override
    public Video getCourse() {
      //制作视频
        return new JavaVideo();
    }

    @Override
    public Article getArticle() {
        // 制作文章
        return new JavaArticle();
    }
}
  • Python工厂
public class PythonCourseFactory implements CourseFactory{
  
    @Override
    public Video getCourse() {
              // 制作视频
        return new PythonVideo();
    }

    @Override
    public Article getArticle() {
        // 制作文章
        return new PythonArticle();
    }
}
  • UML类图

设计模式-抽象工厂模式_第1张图片

  • 测试类
public class Test {

    public static void main(String[] args) {
        // 子类实例指向父类引用
        CourseFactory abstractFactory = new JavaCourseFactory();
        Article article = abstractFactory.getArticle();
        Video course = abstractFactory.getCourse();
        article.produce();
        course.produce();

    }
}

image-20211021220531248

6.对比学习

​ 实现了抽象工厂,我们很自然想到之前学习过的工厂模式。那么这两者有什么区别呢?简单地来说,工厂模式是对一种产品进行工厂加工,对外提供获取这个产品的方法;抽象工厂是对一个产品族下的一些列产品进行工厂加工。听起来还是很抽象,看下例子吧:

  • 工厂模式:鼠标工厂设计模式-抽象工厂模式_第2张图片
  • 抽象工厂:电脑工厂(包括创建鼠标及键盘)

    设计模式-抽象工厂模式_第3张图片

    ​ 综上来说,抽象工厂是对工厂模式的一种扩展,丰富创建产品的种类。就好像一个餐厅,只卖午餐,那就是一个午餐的工厂模式;而这个餐厅早上买早餐,中午买午餐,晚上搞夜市,这是一个餐厅的抽象工厂

7.源码

Mybatis中的抽象工厂

MyBatis在创建SqlSession和Configuration对象时,使用的就是抽象工厂,保证了调用者从一个工厂对象中取出的SqlSession和Configuration是配套的。比如MySQL工厂中取出的就是MySQL的SqlSession和Configuration,Oracle工厂中取出的就是Oracle的SqlSession和Configuration。

设计模式-抽象工厂模式_第4张图片

DefaultSqlSessionFactory实现了抽象工厂SqlSessionFactory,可以直接返回配置信息及sqlsession

public class DefaultSqlSessionFactory implements SqlSessionFactory {

  private final Configuration configuration;

  public DefaultSqlSessionFactory(Configuration configuration) {
    this.configuration = configuration;
  }

      ....
     
  @Override
  public SqlSession openSession(ExecutorType execType, boolean autoCommit) {
    return openSessionFromDataSource(execType, null, autoCommit);
  }

  @Override
  public Configuration getConfiguration() {
    return configuration;
  }

  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }
}

你可能感兴趣的:(java设计模式抽象工厂模式)