工厂方法模式定义
工厂模式的英文原话是:
Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclass.

意思是:定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。

这段话大家都懂,但为什么要这样做呢?下面我用一个例子来讲解一下
看一下简单工厂模式是怎样的,先看代码

public class Demo1 {

    public static void main(String[] args) {
        IFruit apple = FruitFactory.createFruit("Apple");
        apple.info();
        IFruit orange = FruitFactory.createFruit("Orange");
        orange.info();
    }

}

class FruitFactory{

    public static IFruit createFruit(String fruitName){
        IFruit iFruit = null;
        switch (fruitName){
            case "Apple":
                iFruit = new Apple();
                break;
            case "Orange":
                iFruit = new Orange();
                break;
        }
        return iFruit;
    }

}

interface IFruit{
    void info();
}

class Apple implements IFruit{

    @Override
    public void info() {
        System.out.println("我是苹果..");
    }
}
class Orange implements IFruit{

    @Override
    public void info() {
        System.out.println("我是橘子..");
    }
}

为了方便观看,我把所有的类/接口都放在一起了
IFruit接口:水果接口
Apple 、Orange :水果接口的实现类
FruitFactory:生产水果的工厂类
FruitFactory的createFruit方法根据传递不同的参数来创建不同的水果,这便是简单工厂模式

那么简单工厂模式的缺点是什么呢?
当我们想要让FruitFactory水果工厂去生产香蕉呢,这时该怎么办?
因为水果类的接口是IFruit,所以想要扩展一个香蕉类很容易

class Banana implements IFruit{
    @Override
    public void info() {
        System.out.println("我是香蕉..");
    }
}

有了Banana 之后,接下来需要修改FruitFactory水果工厂了

class FruitFactory{

    public static IFruit createFruit(String fruitName){
        IFruit iFruit = null;
        switch (fruitName){
            case "Apple":
                iFruit = new Apple();
                break;
            case "Orange":
                iFruit = new Orange();
                break;
            case "Banana":
                iFruit = new Banana();
                break;
        }
        return iFruit;
    }

}

可以看到我们新增了case "Banana"判断
这样直接去修改FruitFactory类显然违背了开闭原则,对扩展开放、对修改关闭
如果对设计原则不太清楚,传送门六大设计原则 每新增一个水果都要去修改FruitFactory工厂类,加多了不仅内容冗余,而且不易维护
那么如何去优化这个问题呢?接下来就引出了今天的主角工厂方法模式

定义一个用于创建对象的接口
工厂类接口IFruitFactory

interface IFruitFactory{
    IFruit createFruit();
}

让子类决定实例化哪个类

class AppleFactory implements IFruitFactory{

    @Override
    public IFruit createFruit() {
        return new Apple();
    }
}
class OrangeFactory implements IFruitFactory{

    @Override
    public IFruit createFruit() {
        return new Orange();
    }
}

来看一下完整Demo

public class Demo2 {

    public static void main(String[] args) {
        IFruitFactory appleFactory = new AppleFactory();
        IFruit apple = appleFactory.createFruit();
        apple.info();
        IFruitFactory orangeFactory = new OrangeFactory();
        IFruit orange = orangeFactory.createFruit();
        orange.info();
    }

}
interface IFruitFactory{
    IFruit createFruit();
}
class AppleFactory implements IFruitFactory{

    @Override
    public IFruit createFruit() {
        return new Apple();
    }
}
class OrangeFactory implements IFruitFactory{

    @Override
    public IFruit createFruit() {
        return new Orange();
    }
}

输出结果

我是苹果..
我是橘子..

那我们如果需要生产香蕉banana该怎么办呢?
只需要创建BananaFactory即可

class BananaFactory implements IFruitFactory{

    @Override
    public IFruit createFruit() {
        return new Orange();
    }
}

无需修改原有的类,只需扩展一个BananaFactory 类,符合开闭原则

IFruitFactory依赖的是IFruit 也符合接口隔离原则,降低耦合,便于扩展

看到了这里,可能有人要问了我要Apple类直接new Apple()不就完了,干嘛还要先创建一个工厂,再通过工厂去创建Apple呢?

如果仅仅是new Apple()确实是不需要这么做,但是如果还需要为Apple对象添加一些属性呢,比如setColor设置颜色,这个例子不太直观

原生jdbc想必大家都有写过吧,需要设置连接url、用户名、密码、驱动类,如果每次获取数据库连接都需要这么操作,那岂不是到处都是这些重复代码,所以这里也会用到工厂类,不仅生产连接数据库对象而且还会将连接url、用户名、密码等参数封装到对象中,这样我们只需要使用工厂类即可,不需要去管连接数据库对象是如何创建的细节

工厂方法模式的优点
良好的封装性 一个对象的创建是有条件约束的,如果一个调用者需要一个具体的产品对象,只要知道这个产品的类名或约束字符串即可,不用知道创建对象的过程如何,降低了模块间的耦合。
优秀的扩展性 在增加产品类的情况下,只要适当地修改具体的工厂类或扩展一个工厂类就可以适应变化

以上就是工厂方法模式的全部内容了
如有不妥,欢迎指点
如有帮助到你,欢迎点个赞再走