【设计模式】创建型-工厂方法模式(Factory Method Pattern)

工厂方法模式(Factory Method Pattern)

  • 1.工厂方法介绍
  • 2.工厂方法案例(2.1-2.3同简单工厂案例)
    • 2.0案例代码结构
    • 2.1抽象勇士类
    • 2.2勇士类型枚举
    • 2.3具体勇士
    • 2.4抽象勇士工厂(工厂模式核心)
    • 2.5具体勇士工厂
    • 2.6案例测试类
    • 2.7扩展创建魔法师
  • 3.优缺点分析
    • 3.1优点
    • 3.2缺点

1.工厂方法介绍

工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现开闭原则,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。

工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。

工厂方法模式(Factory Method pattern)是最典型的模板方法模式(Template Method pattern)应用。

它的核心结构有四个角色,分别是抽象工厂;具体工厂;抽象产品;具体产品

2.工厂方法案例(2.1-2.3同简单工厂案例)

上一篇博客简单工厂模式案例中不符合开闭原则,所以又衍生出一种更加好的生产方式,这就是工厂方法模式。把生产勇士的工厂类抽象成接口或抽象类,让具体的工厂类实现接口或继承抽象类,需要哪个类型的勇士就实例化那种工厂,生产出具体的勇士来。简单工厂中不存在的魔法师这里就将它创建出来。

2.0案例代码结构

【设计模式】创建型-工厂方法模式(Factory Method Pattern)_第1张图片

2.1抽象勇士类

采用抽象类代替接口,抽象类可以更好地实现模板功能。

/**
 * 抽象的勇士
 */
public abstract class AbstractFighter {
	//勇士编号
    private int id;
    public AbstractFighter(int id) {
        this.id = id;
    }
    public void say() {
        System.out.println("我是" + this.getFighterType().getTypeName() + ", 编号:" + this.id);
    }
    abstract FighterType getFighterType();
}

2.2勇士类型枚举

约束勇士种类,传参可视化。

/**
 * 勇士类型枚举
 */
public enum FighterType {
    Gunner("神枪手"),
    Swordman("鬼剑士"),
    Mage("魔法师");
    private String typeName;
    private FighterType(String typeName) {
        this.typeName = typeName;
    }
    public String getTypeName() {
        return this.typeName;
    }
}

2.3具体勇士

使用原子操作类AtomicInteger,利用唯一编号动态管理同类对象。

/**
 * 神枪手
 */
public class Gunner extends AbstractFighter {
    private static AtomicInteger fighterID = new AtomicInteger(0);
    public Gunner() {
        super(fighterID.addAndGet(1));
    }
    @Override
    FighterType getFighterType() {
        return FighterType.Gunner;
    }
}

/**
 * 鬼剑士
 */
public class Swordman extends AbstractFighter {
    private static AtomicInteger fighterID = new AtomicInteger(0);
    public Swordman() {
        super(fighterID.addAndGet(1));
    }
    @Override
    FighterType getFighterType() {
        return FighterType.Swordman;
    }
}

以上代码均与简单工厂模式中一样,变化的是工厂,代码如下:

2.4抽象勇士工厂(工厂模式核心)

/**
 * 抽象的勇士工厂
 */
public abstract class AbstractFighterFactory {
    /**
     * 抽象方法-创建勇士
     * @return
     */
    public abstract AbstractFighter createFighter();
}

2.5具体勇士工厂

/**
 * 神枪手工厂
 */
public class GunnerFactory extends AbstractFighterFactory {
    @Override
    public AbstractFighter createFighter() {
        return new Gunner();
    }
}
/**
 * 鬼剑士工厂
 */
public class SwordmanFactory extends AbstractFighterFactory {
    @Override
    public AbstractFighter createFighter() {
        return new Swordman();
    }
}

2.6案例测试类

public class FactoryMethodTest {
    public static void main(String[] args) {
        //创建神枪手工厂
        AbstractFighterFactory gunnerFactory = new GunnerFactory();
        //创建神枪手
        AbstractFighter fighter1_1 = gunnerFactory.createFighter();
        fighter1_1.say();
        AbstractFighter fighter1_2 = gunnerFactory.createFighter();
        fighter1_2.say();

        //创建鬼剑士工厂
        AbstractFighterFactory swordmanFactory = new SwordmanFactory();
        //创建鬼剑士
        AbstractFighter fighter2_1 = swordmanFactory.createFighter();
        fighter2_1.say();
        AbstractFighter fighter2_2 = swordmanFactory.createFighter();
        fighter2_2.say();
    }
}

输出结果如下:

我是神枪手, 编号:1
我是神枪手, 编号:2
我是鬼剑士, 编号:1
我是鬼剑士, 编号:2

2.7扩展创建魔法师

如果我需要再创建一个魔法师,我只需写一个具体的魔法师类(继承抽象的勇士类)和一个魔法师工厂(继承抽象的勇士工厂即可),不需要修改源代码。

/**
 * 魔法师
 */
public class Mage extends AbstractFighter {
    private static AtomicInteger fighterID = new AtomicInteger(0);
    public Mage() {
        super(fighterID.addAndGet(1));
    }
    @Override
    FighterType getFighterType() {
        return FighterType.Mage;
    }
}
/**
 * 魔法师工厂
 */
public class MageFactory extends AbstractFighterFactory {
    @Override
    public AbstractFighter createFighter() {
        return new Mage();
    }
}
public class FactoryMethodTest {
    public static void main(String[] args) {
        //创建魔法师工厂
        AbstractFighterFactory mageFactory = new MageFactory();
        //创建魔法师
        AbstractFighter fighter3_1 = mageFactory.createFighter();
        fighter3_1.say();
        AbstractFighter fighter3_2 = mageFactory.createFighter();
        fighter3_2.say();
    }
}

输出结果如下:

我是魔法师, 编号:1
我是魔法师, 编号:2

3.优缺点分析

3.1优点

工厂方法模式克服了简单工厂会违背开闭原则的缺点,又保持了封装对象创建过程的优点。
符合单一职责原则,每个具体工厂类只负责创建对应的产品。

3.2缺点

每增加一个产品类,就需要增加一个对应的产品工厂类,增加了额外的开发量。

你可能感兴趣的:(设计模式入门)