目录

  • 一、工厂模式
  • 1.1 简单工厂模式
  • 1.2 工厂方法模式
  • 1.3 抽象工厂模式


一、工厂模式

核心
1、实例化对象不再用new,用工厂方法
2、选择实现类,创建对象统一管理和控制,从而将调用者跟实现类解耦。调用者不用知道实现类的细节,直接使用即可,实现细节交给工厂。

这两句话很重要,我们在后面代码中会体会到。
工厂模式又可分为三种模式:
(1)简单工厂模式
(2)工厂方法模式
(3)抽象工厂模式

所属类型:创建型模式(new对象的作用)

1.1 简单工厂模式

这里我们用消费者买车的案例,小明要买车,从大众和长安汽车选一辆,我们先用原始的接口和实现类来写,先分析有哪些对象:Consumer对象,DZCar对象,CACar对象,Car接口

public class Consumer {
    public static void main(String[] args) {
        Car car1 = new CACar();
        Car car2 = new DZCar();
        car1.name();
        car2.name();
    }
}
//长安
public class CACar implements Car{
    @Override
    public void name() {
        System.out.println("长安汽车");
    }
}
//大众
public class DZCar implements Car{

    @Override
    public void name() {
        System.out.println("大众汽车");
    }
}
public interface Car {
    void name();
}

运行Consumer结果

Java 工厂模式 设计模式 java工厂模式三种详解_java


但是这里还需要自己new,也就是自己要写具体实现类,如果是买车的话,消费者怎么会自己实现一个车呢,如果会造车,还要买干啥,所以造车就交给工厂,我们买的是工厂生产组装后的车,也就是具体怎么实现这个车的细节交给工厂,如下

public class CarFactory {
    public static Car getCar(String carName){
        if(carName.equals("长安汽车")){
            return new CACar();
        }else if (carName.equals("大众汽车")){
            return new DZCar();
        }else {
            return null;
        }
    }
}

Consumer.java修改为如下

public class Consumer {
    public static void main(String[] args) {
        Car car1 = CarFactory.getCar("长安汽车");
        Car car2 = CarFactory.getCar("大众汽车");
        car1.name();
        car2.name();
    }
}

Java 工厂模式 设计模式 java工厂模式三种详解_java_02


结果相同,但是这就符合工厂模式了,消费者买车,就直接说一个车名就行,具体这个车怎么造的交给工厂,消费者拿到造好的车就行,上面就是一个简单工厂模式,很容易理解,但是如果消费者又想看看其他车,那么就要新增几行代码,再加一个else if,这明显就不符合开发的开闭原则,就是扩展时不能修改原有代码,所以简单工厂模式只是理解一下工厂模式大概是什么,接下来介绍工厂方法模式,让其符合开闭原则(对扩展开放,对修改关闭,修改是不能对原有代码修改)。

Java 工厂模式 设计模式 java工厂模式三种详解_java_03

1.2 工厂方法模式

简而言之,就是每种车都有自己的工厂,而不是所有车共用一个工厂,更符合我们现在的生活,什么牌子汽车都来自自己的车工厂,所以CarFactory变成一个公共接口,创建多个车工厂实现这个接口。

//工厂方法模式
public interface CarFactory {
    Car getCar();
}
//大众车工厂
public class DZFactory implements CarFactory{
    @Override
    public Car getCar() {
        return new DZCar();
    }
}
//长安车工厂
public class CAFactory implements CarFactory{
    @Override
    public Car getCar() {
        return new CACar();
    }
}
public class Consumer {
    public static void main(String[] args) {
        Car car1 = new CAFactory().getCar();
        Car car2 = new DZFactory().getCar();
        car1.name();
        car2.name();
    }
}

运行结果如下

Java 工厂模式 设计模式 java工厂模式三种详解_Java 工厂模式 设计模式_04

相比简单工厂模式只有一个工厂,工厂方法模式有多个工厂,运行后结果相同,但是设计不同,这里就用到工厂方法模式,符合开闭原则(对扩展开放,对修改关闭),逻辑上也更符合现实情况,什么牌子车对应什么牌子车工厂制造,而不是只有一个工厂,如果消费者想再看看宝马车,那么就直接创建一个宝马类和宝马车工厂即可,无需改动原有代码

Java 工厂模式 设计模式 java工厂模式三种详解_ide_05

public class BMWCar implements Car{
    @Override
    public void name() {
        System.out.println("宝马汽车");
    }
}
public class BMWFactory implements CarFactory{
    @Override
    public Car getCar() {
        return new BMWCar();
    }
}
public class Consumer {
    public static void main(String[] args) {
        Car car1 = new CAFactory().getCar();
        Car car2 = new DZFactory().getCar();
        car1.name();
        car2.name();

		Car car3 = new BMWFactory().getCar();
        car3.name();
    }
}

Java 工厂模式 设计模式 java工厂模式三种详解_Java 工厂模式 设计模式_06


这样要看什么车都只要新增,不会对之前代码修改,符合开闭原则

Java 工厂模式 设计模式 java工厂模式三种详解_工厂模式_07

这样工厂方法模式确实符合了开闭原则,新增代码不会改动原来代码,但是会有一个问题,如果一直新增类,比如几十个牌子的车,那类会太多,太庞大,导致过于复杂,所以有时为了简单,虽然不符合设计原则,但也会直接设计成简单工厂模式,并且这种情况还不少。

Java 工厂模式 设计模式 java工厂模式三种详解_ide_08

1.3 抽象工厂模式

抽象工厂就是对产品功能的抽象,上层设计只需设计有哪些功能,具体功能实现交给工厂去做。比如有两个产品接口,手机和路由器

//手机产品
public interface PhoneProduct {
    void playGame();//玩游戏
    void call();//打电话
    void sendMsg();//发消息
}
//路由器产品
public interface RouteProduct {
    void openWlan();//打开Wlan
    void setWlanPwd();//设置wlan密码
}
//小米手机
public class XiaoMiPhone implements PhoneProduct{
    @Override
    public void playGame() {
        System.out.println("小米手机玩游戏");
    }

    @Override
    public void call() {
        System.out.println("小米手机打电话");
    }

    @Override
    public void sendMsg() {
        System.out.println("小米手机发短信");
    }
}
//华为手机
public class HuaWeiPhone implements PhoneProduct{
    @Override
    public void playGame() {
        System.out.println("华为手机玩游戏");
    }

    @Override
    public void call() {
        System.out.println("华为手机打电话");
    }

    @Override
    public void sendMsg() {
        System.out.println("华为手机发短信");
    }
}
//小米路由器
public class XiaoMiRoute implements RouteProduct{
    @Override
    public void openWlan() {
        System.out.println("小米路由器连接wlan");
    }

    @Override
    public void setWlanPwd() {
        System.out.println("小米路由器设置密码");
    }
}
//华为路由器
public class HuaWeiRoute implements RouteProduct{
    @Override
    public void openWlan() {
        System.out.println("华为路由器连接wlan");
    }

    @Override
    public void setWlanPwd() {
        System.out.println("华为路由器设置密码");
    }
}

这里就是一个工厂可以生产很多产品,具体怎么生产不用抽象产品工厂管,具体工厂去实现生产就行

//抽象产品工厂(抽象工厂模式,这里就是抽象的抽象,ProductFactory 是接口,内部也是接口,也就是不关注实现,自身设计有哪些功能行为即可)
public interface ProductFactory {

    PhoneProduct phoneProduct();//生产手机

    RouteProduct routeProduct();//生产路由器
    
}
//小米工厂
public class XiaoMiFactory implements ProductFactory{
    @Override
    public PhoneProduct phoneProduct() {
        return new XiaoMiPhone();
    }

    @Override
    public RouteProduct routeProduct() {
        return new XiaoMiRoute();
    }
}
//华为工厂
public class HuaWeiFactory implements ProductFactory{
    @Override
    public PhoneProduct phoneProduct() {
        return new HuaWeiPhone();
    }

    @Override
    public RouteProduct routeProduct() {
        return new HuaWeiRoute();
    }
}
public class Client {
    public static void main(String[] args) {
        System.out.println("=========小米系列产品=========");
        PhoneProduct phoneProduct = new XiaoMiFactory().phoneProduct();//小米工厂生产手机
        phoneProduct.sendMsg();
        phoneProduct.call();
        phoneProduct.playGame();

        RouteProduct routeProduct = new XiaoMiFactory().routeProduct();//工厂生产
        routeProduct.openWlan();
        routeProduct.setWlanPwd();
        System.out.println("=========华为系列产品=========");
        PhoneProduct phoneProduct1 = new HuaWeiFactory().phoneProduct();
        phoneProduct1.playGame();
        phoneProduct1.call();

    }
}

如果需要生产一个新的产品,比如造车,那么只要在ProductFactory新增carProduct()即可,然后交给具体工厂实现即可,不会修改原有代码,只要新增对应功能即可,但新增后可能需要其所有实现类进行实现,所以抽象工厂模式适用于长期稳定的生产某些指定产品,不会频繁变动需要生产的产品,比如设计之初就生产手机和路由器,不生产别的,那么抽象工厂就非常适合,也十分强大。

Java 工厂模式 设计模式 java工厂模式三种详解_spring_09


具体用哪种工厂模式,根据具体实际业务决定。

参考视频:https://www.bilibili.com/video/BV1mc411h719?p=3