侧边栏壁纸
博主头像
赫兹

谁辜负过自己,说不上可惜

  • 累计撰写 18 篇文章
  • 累计创建 13 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

抽象工厂

赫兹
2022-09-30 / 0 评论 / 0 点赞 / 369 阅读 / 1,141 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-10-11,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

抽象工厂

意图

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

说明

🥝举个栗子

为了创造一个王国,我们需要有一个具有共同特征的对象。精灵王国需要精灵国王、精灵城堡和精灵军队,而兽人王国需要兽人国王、兽人城堡和兽人军队。王国中的物体之间存在依赖关系。

🥝简单的说

抽象工厂模式提供了一种方法,可以封装一组具有共同特征的单个工厂,而无需指定它们的具体实现类

🥝编程示例

首先,根据上面的例子,为王国中的对象提供一些接口和实现

/**
 * 城堡接口
 */
public interface Castle {
  String getDescription();
}
/**
 * 国王接口
 */
public interface King {
  String getDescription();
}
/**
 * 军队接口
 */
public interface Army {
  String getDescription();
}

// 精灵具体实现 ->
public class ElfCastle implements Castle {
  static final String DESCRIPTION = "这是一个精灵的城堡!";
  @Override
  public String getDescription() {
    return DESCRIPTION;
  }
}
public class ElfKing implements King {
  static final String DESCRIPTION = "这是一位精灵王!";
  @Override
  public String getDescription() {
    return DESCRIPTION;
  }
}
public class ElfArmy implements Army {
  static final String DESCRIPTION = "这是一支精灵军队!";
  @Override
  public String getDescription() {
    return DESCRIPTION;
  }
}

// 兽人的具体实现也类似 -> ...

然后我们就有了王国工厂的抽象和实现。

public interface KingdomFactory {
  //给王国创建一个城堡
  Castle createCastle();
  //给王国任命一个国王
  King createKing();
  //给王国创建一支军队
  Army createArmy();
}

//创建精灵王国工厂的具体实现
public class ElfKingdomFactory implements KingdomFactory {

  @Override
  public Castle createCastle() {
    return new ElfCastle();
  }

  @Override
  public King createKing() {
    return new ElfKing();
  }

  @Override
  public Army createArmy() {
    return new ElfArmy();
  }
}

//创建兽人王国工厂的具体实现
public class OrcKingdomFactory implements KingdomFactory {

  @Override
  public Castle createCastle() {
    return new OrcCastle();
  }

  @Override
  public King createKing() {
    return new OrcKing();
  }
  
  @Override
  public Army createArmy() {
    return new OrcArmy();
  }
}

现在我们有了一个抽象工厂,它让我们可以创建一系列相关对象,即精灵王国工厂创建精灵城堡、国王和军队等。

var factory = new ElfKingdomFactory();
var castle = factory.createCastle();
var king = factory.createKing();
var army = factory.createArmy();

castle.getDescription();
king.getDescription();
army.getDescription();

程序输出

This is the elven castle!
This is the elven king!
This is the elven Army!

现在,我们可以为我们不同的王国设计工厂。在本例中,我们创建了FactoryMaker,负责返回ElfKingdomFactoryOrcKingdomFactory的实例。
客户端(调用方)可以使用FactoryMake创建所需的工厂,进而生产不同的工厂对象。
在这个例子中,我们还使用了一个枚举来参数化客户端的王国工厂的类型。

public static class FactoryMaker {

  public enum KingdomType {
    ELF, ORC
  }

  public static KingdomFactory makeFactory(KingdomType type) {
    switch (type) {
      case ELF:
        return new ElfKingdomFactory();
      case ORC:
        return new OrcKingdomFactory();
      default:
        throw new IllegalArgumentException("KingdomType not supported.");
    }
  }
}

public static void main(String[] args) {
  var app = new App();

  LOGGER.info("开始创建精灵王国");
  app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
  LOGGER.info(app.getArmy().getDescription());
  LOGGER.info(app.getCastle().getDescription());
  LOGGER.info(app.getKing().getDescription());

  LOGGER.info("开始创建兽人王国");
  app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
  -- similar use of the orc factory
}

类图

abstract-factory.urm

适用场景

  • 系统应独立于其产品的创建、组成和表示方式

  • 系统应配置多个产品系列中的一个

  • 相关产品对象需必须要在一起使用,需要保证产品一致性时

  • 您想提供产品的类库,并且只想显示它们的接口,而不是具体的实现

  • 在程序运行时,来构造特定的依赖项或调用那个产品

  • 在向程序中添加新产品或产品系列时,您不希望更改现有代码。

优点

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

缺点

  • java中的依赖注入隐藏了服务类依赖项,这些依赖项可能会导致运行时错误在编译时就被捕获

  • 虽然在创建预定义对象时非常有用,但添加新对象(扩展新产品)可能会很复杂

  • 由于大量新接口和类与模式一起引入,增加了系统的抽象性和理解难度

其它教程

经典案例

获取源码

👉更多设计模式的源码,都整理到githup上了

0

评论区