【设计模式-2.4】创建型——抽象工厂模式

说明:本文介绍设计模式中,创建型设计模式的抽象工厂设计模式;

工厂模式的问题

【设计模式-2.2】创建型——简单工厂和工厂模式这篇博文中,介绍过飞机大战游戏里,使用简单工厂和工厂模式来创建坦克、飞机、Boss对象。

在这里插入图片描述

如果对象的类型过多,我们就需要创建更多的工厂类,并且如果我们需要对对象进行分类,如按照等级分类,坦克、飞机属于低等敌人,Boss属于高等敌人;按照战斗场景分类,坦克属于陆地,飞机属于天空,Boss可在陆地或者天空。

这就需要我们对现有的工厂类进一步抽取,抽象。

抽象工厂模式

在《秒懂设计模式》这本书中,提供了一种使用场景。如下:

在这里插入图片描述

作者假设某公司需要开发一款星际战争的游戏,游戏中兵种可分为人类与外星怪兽2个族,其中每个族又可分为1级、2级和3级,不同等级的兵种,攻击力、防御力和生命值不同;

(兵种接口)

/**
 * 兵种抽象类
 */
public abstract class Unit {
   

    /**
     * 攻击力
     */
    protected int attack;

    /**
     * 防御力
     */
    protected int defence;

    /**
     * 生命值
     */
    protected int health;

    /**
     * 横坐标
     */
    protected int x;

    /**
     * 纵坐标
     */
    protected int y;

    public Unit(int attack, int defence, int health, int x, int y) {
   
        this.attack = attack;
        this.defence = defence;
        this.health = health;
        this.x = x;
        this.y = y;
    }

    /**
     * 出现
     */
    public abstract void show();

    /**
     * 攻击
     */
    public abstract void attack();
}

(低级兵种)

/**
 * 低级兵种
 */
public abstract class LowClassUnit extends Unit{
   

    /**
     * 低级兵种
     * @param x
     * @param y
     */
    public LowClassUnit(int x, int y) {
   
        super(5, 2, 35, x, y);
    }
}

(中级兵种)

/**
 * 中级兵种
 */
public abstract class MidClassUnit extends Unit{
   

    /**
     * 中级兵种
     * @param x
     * @param y
     */
    public MidClassUnit(int x, int y) {
   
        super(10, 8, 80, x, y);
    }
}

(高级兵种)

/**
 * 高级兵种
 */
public abstract class HighClassUnit extends Unit{
   

    /**
     * 高级兵种
     * @param x
     * @param y
     */
    public HighClassUnit(int x, int y) {
   
        super(25, 30, 300, x, y);
    }
}

(人族,低级兵种,海军陆战队)

/**
 * 海军陆战队
 */
public class Marine extends LowClassUnit {
   

    public Marine(int x, int y) {
   
        super(x, y);
    }

    @Override
    public void show() {
   
        System.out.println("海军陆战队出现了,坐标为:(" + x + "," + y + ")");
    }

    @Override
    public void attack() {
   
        System.out.println("海军陆战队攻击,攻击力为:" + attack);
    }
}

(人族,中级兵种,变形坦克)

/**
 * 变形坦克
 */
public class Tank extends MidClassUnit{
   

    /**
     * 中级兵种
     *
     * @param x
     * @param y
     */
    public Tank(int x, int y) {
   
        super(x, y);
    }

    @Override
    public void show() {
   
        System.out.println("变形坦克出现了,坐标为:(" + x + "," + y + ")");
    }

    @Override
    public void attack() {
   
        System.out.println("变形坦克攻击,攻击力为:" + attack);
    }
}

(人族,高级兵种,巨型战舰)

/**
 * 巨型战舰
 */
public class Battleship extends HighClassUnit{
   

    /**
     * 高级兵种
     *
     * @param x
     * @param y
     */
    public Battleship(int x, int y) {
   
        super(x, y);
    }

    @Override
    public void show() {
   
        System.out.println("巨型战舰出现了,坐标为:(" + x + "," + y + ")");
    }

    @Override
    public void attack() {
   
        System.out.println("巨型战舰攻击,攻击力为:" + attack);
    }
}

(怪兽族,低级兵种,螳螂)

/**
 * 螳螂
 */
public class Roach extends LowClassUnit{
   

    /**
     * 低级兵种
     *
     * @param x
     * @param y
     */
    public Roach(int x, int y) {
   
        super(x, y);
    }

    @Override
    public void show() {
   
        System.out.println("螳螂出现了,坐标为:(" + x + "," + y + ")");
    }

    @Override
    public void attack() {
   
        System.out.println("螳螂攻击,攻击力为:" + attack);
    }
}

(怪兽组,中级兵种,毒液)

/**
 * 毒液
 */
public class Poison extends MidClassUnit {
   

    /**
     * 中级兵种
     *
     * @param x
     * @param y
     */
    public Poison(int x, int y) {
   
        super(x, y);
    }

    @Override
    public void show() {
   
        System.out.println("毒液出现了,坐标为:(" + x + "," + y + ")");
    }

    @Override
    public void attack() {
   
        System.out.println("毒液攻击,攻击力为:" + attack);
    }
}

(怪兽组,高级兵种,猛犸)

/**
 * 猛犸
 */
public class Mammoth extends HighClassUnit {
   

    /**
     * 高级兵种
     *
     * @param x
     * @param y
     */
    public Mammoth(int x, int y) {
   
        super(x, y);
    }

    @Override
    public void show() {
   
        System.out.println("猛犸出现了,坐标为:(" + x + "," + y + ")");
    }

    @Override
    public void attack() {
   
        System.out.println("猛犸攻击,攻击力为:" + attack);
    }
}

如果使用工厂模式来设计,那么需要创建6个工厂类,且这些工厂类互相没有联系,因此我们考虑使用抽象工厂模式,如下:

(抽象兵种工厂)

/**
 * 抽象兵种工厂
 */
public interface AbstractFactory {
   

    /**
     * 创建低级兵种
     * @return
     */
    LowClassUnit createLowClassUnit();

    /**
     * 创建中级兵种
     * @return
     */
    MidClassUnit createMidClassUnit();

    /**
     * 创建高级兵种
     * @return
     */
    HighClassUnit createHighClassUnit();
}

(人类兵种工厂)

/**
 * 人类兵种工厂
 */
public class HumanFactory implements AbstractFactory {
   

    /**
     * 横坐标
     */
    private int x;

    /**
     * 纵坐标
     */
    private int y;

    public HumanFactory(int x, int y) {
   
        this.x = x;
        this.y = y;
    }

    @Override
    public LowClassUnit createLowClassUnit() {
   
        LowClassUnit unit = new Marine(x, y);
        System.out.println("制造海军陆战队员成功。");
        return unit;
    }

    @Override
    public MidClassUnit createMidClassUnit() {
   
        MidClassUnit unit = new Tank(x, y);
        System.out.println("制造变形坦克成功。");
        return unit;
    }

    @Override
    public HighClassUnit createHighClassUnit() {
   
        HighClassUnit unit = new Battleship(x, y);
        System.out.println("制造巨型战舰成功。");
        return unit;
    }
}

(外星怪兽兵种工厂)

/**
 * 外星人兵种工厂
 */
public class AlienFactory implements AbstractFactory {
   

    /**
     * 横坐标
     */
    private int x;

    /**
     * 纵坐标
     */
    private int y;

    public AlienFactory(int x, int y) {
   
        this.x = x;
        this.y = y;
    }

    @Override
    public LowClassUnit createLowClassUnit() {
   
        LowClassUnit unit = new Roach(x, y);
        System.out.println("制造蟑螂成功。");
        return unit;
    }

    @Override
    public MidClassUnit createMidClassUnit() {
   
        MidClassUnit unit = new Poison(x, y);
        System.out.println("制造毒液成功。");
        return unit;
    }

    @Override
    public HighClassUnit createHighClassUnit() {
   
        HighClassUnit unit = new Mammoth(x, y);
        System.out.println("制造猛犸象成功。");
        return unit;
    }
}

(客户端,演示人类兵种、怪兽兵种的创建)

/**
 * 客户端
 */
public class Client {
   
    public static void main(String[] args) {
   

        System.out.println("......人类兵种工厂开始制造兵种......");

        // 创建人类兵种工厂
        AbstractFactory humanFactory = new HumanFactory(10, 10);
        // 创建低级兵种
        LowClassUnit humanLowClassUnit = humanFactory.createLowClassUnit();
        // 创建中级兵种
        MidClassUnit humanMidClassUnit = humanFactory.createMidClassUnit();
        // 创建高级兵种
        HighClassUnit humanHighClassUnit = humanFactory.createHighClassUnit();

        // 低级兵种展示和攻击
        humanLowClassUnit.show();
        humanLowClassUnit.attack();

        // 中级兵种展示和攻击
        humanMidClassUnit.show();
        humanMidClassUnit.attack();

        // 高级兵种展示和攻击
        humanHighClassUnit.show();
        humanHighClassUnit.attack();

        System.out.println("==========================================================");

        System.out.println("......外星人兵种工厂开始制造兵种......");
        // 创建外星人兵种工厂
        AbstractFactory alienFactory = new AlienFactory(200, 200);
        // 创建低级兵种
        LowClassUnit alienLowClassUnit = alienFactory.createLowClassUnit();
        // 创建中级兵种
        MidClassUnit alienMidClassUnit = alienFactory.createMidClassUnit();
        // 创建高级兵种
        HighClassUnit alienHighClassUnit = alienFactory.createHighClassUnit();
        
        // 低级兵种展示和攻击
        alienLowClassUnit.show();
        alienLowClassUnit.attack();

        // 中级兵种展示和攻击
        alienMidClassUnit.show();
        alienMidClassUnit.attack();

        // 高级兵种展示和攻击
        alienHighClassUnit.show();
        alienHighClassUnit.attack();
    }
}

以上是抽象工厂模式创建对象的过程。抽象工厂模式是对工厂模式的一种提炼,当我们需要对系统中的对象进行分类区别时,应当考虑使用抽象工厂模式。

总结

本文参考《设计模式的艺术》、《秒懂设计模式》两书,代码来自《秒懂设计模式》,略有不同。

相关推荐

  1. GO设计模式——3、抽象工厂模式创建

    2023-12-18 07:42:04       59 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-18 07:42:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-18 07:42:04       101 阅读
  3. 在Django里面运行非项目文件

    2023-12-18 07:42:04       82 阅读
  4. Python语言-面向对象

    2023-12-18 07:42:04       91 阅读

热门阅读

  1. Kotlin(十六) 高阶函数的简单应用

    2023-12-18 07:42:04       55 阅读
  2. Spring Boot Kotlin支持中文文档

    2023-12-18 07:42:04       57 阅读
  3. 《Kotlin核心编程》笔记:设计模式

    2023-12-18 07:42:04       46 阅读
  4. kafka入门(四):kafka生产者发送消息

    2023-12-18 07:42:04       55 阅读
  5. 基于Spring、SpringMVC、MyBatis的校园订餐系统

    2023-12-18 07:42:04       69 阅读
  6. 开源语音识别faster-whisper部署教程

    2023-12-18 07:42:04       67 阅读
  7. C# 内存的分配管理

    2023-12-18 07:42:04       56 阅读
  8. React 表单与事件

    2023-12-18 07:42:04       54 阅读