所有分类
  • 所有分类
  • 未分类

工厂模式Java实战–写法3:抽象工厂模式

简介

本文介绍工厂模式的抽象工厂模式。

抽象工厂:用来生产其他工厂的工厂。

适用场景

抽象工厂适用于多个品牌、多种产品类型的情况。

优缺点

优点

管理多个品牌、多个类型时,很方便。

缺点

增加新的产品类型时比较麻烦。

源码中的应用

  1. Spring中IOC容器创建/管理Bean对象
  2. 反射中Class对象的newInstance方法
  3. JDBC中的Connection对象的获取
  4. JDK中Calendar的getInstance方法

实例

需求:如上边“适用场景”所示,提供小米和华为两个品牌,手机和路由器两种类型。

代码结构

手机产品

接口

package com.knife.designPattern.product.phone;
 
public interface Phone {
    /**
     * 打电话
     */
    String callUp();
}

小米实现类

package com.knife.designPattern.product.phone.impl;

import com.knife.designPattern.product.phone.Phone;
import lombok.Data;

@Data
public class XiaoMiPhoneImpl implements Phone {
    /**
     * CPU个数
     */
    private Integer cpuCount;

    /**
     * 内存大小
     */
    private Integer memoryStorage;

    public XiaoMiPhoneImpl(Integer cpuCount, Integer memoryStorage) {
        this.cpuCount = cpuCount;
        this.memoryStorage = memoryStorage;
    }
 
    @Override
    public String callUp() {
        return "小米手机打电话";
    }
}

华为实现类

package com.knife.designPattern.product.phone.impl;

import com.knife.designPattern.product.phone.Phone;
import lombok.Data;

@Data
public class HuaWeiPhoneImpl implements Phone {
    /**
     * CPU个数
     */
    private Integer cpuCount;

    /**
     * 内存大小
     */
    private Integer memoryStorage;

    public HuaWeiPhoneImpl(Integer cpuCount, Integer memoryStorage) {
        this.cpuCount = cpuCount;
        this.memoryStorage = memoryStorage;
    }

    @Override
    public String callUp() {
        return "华为手机打电话";
    }
}

路由器产品

接口

package com.knife.designPattern.product.router;
 
public interface Router {
    /**
     * 接收网络数据
     */
    String receiveNetworkData();
}

小米实现类

package com.knife.designPattern.product.router.impl;

import com.knife.designPattern.product.router.Router;
import lombok.Data;

@Data
public class XiaoMiRouterImpl implements Router {
    /**
     * 网速
     */
    private Integer networkSpeed;

    /**
     * 插口数量
     */
    private Integer slotCount;

    public XiaoMiRouterImpl(Integer networkSpeed, Integer slotCount) {
        this.networkSpeed = networkSpeed;
        this.slotCount = slotCount;
    }
 
    @Override
    public String receiveNetworkData() {
        return "小米路由器接收网络数据";
    }
}

华为实现类

package com.knife.designPattern.product.router.impl;

import com.knife.designPattern.product.router.Router;
import lombok.Data;

@Data
public class HuaWeiRouterImpl implements Router {
    /**
     * 网速
     */
    private Integer networkSpeed;

    /**
     * 插口数量
     */
    private Integer slotCount;

    public HuaWeiRouterImpl(Integer networkSpeed, Integer slotCount) {
        this.networkSpeed = networkSpeed;
        this.slotCount = slotCount;
    }

    @Override
    public String receiveNetworkData() {
        return "华为路由器接收网络数据";
    }
}

工厂

接口

package com.knife.designPattern.factory;

import com.knife.designPattern.product.phone.Phone;
import com.knife.designPattern.product.router.Router;

public interface ProductFactory {
    Phone createPhone();

    Router createRouter();
}

小米实现类

package com.knife.designPattern.factory.impl;

import com.knife.designPattern.factory.ProductFactory;
import com.knife.designPattern.product.phone.Phone;
import com.knife.designPattern.product.phone.impl.XiaoMiPhoneImpl;
import com.knife.designPattern.product.router.Router;
import com.knife.designPattern.product.router.impl.XiaoMiRouterImpl;

public class XiaoMiFactoryImpl implements ProductFactory {
    public Phone createPhone() {
        return new XiaoMiPhoneImpl(4, 21);
    }

    @Override
    public Router createRouter() {
        return new XiaoMiRouterImpl(100, 5);
    }
}

华为实现类

package com.knife.designPattern.factory.impl;

import com.knife.designPattern.factory.ProductFactory;
import com.knife.designPattern.product.phone.Phone;
import com.knife.designPattern.product.phone.impl.HuaWeiPhoneImpl;
import com.knife.designPattern.product.router.Router;
import com.knife.designPattern.product.router.impl.HuaWeiRouterImpl;

public class HuaWeiFactoryImpl implements ProductFactory {
    public Phone createPhone() {
        return new HuaWeiPhoneImpl(4, 21);
    }

    @Override
    public Router createRouter() {
        return new HuaWeiRouterImpl(100, 5);
    }
}

测试类

package com.knife.designPattern.controller;

import com.knife.designPattern.factory.ProductFactory;
import com.knife.designPattern.factory.impl.HuaWeiFactoryImpl;
import com.knife.designPattern.factory.impl.XiaoMiFactoryImpl;
import com.knife.designPattern.product.phone.Phone;
import com.knife.designPattern.product.router.Router;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Api(tags = "产品")
@RestController
@RequestMapping("product")
public class ProductController {
    @ApiOperation("手机")
    @GetMapping("phone")
    public String phone(String name) {
        ProductFactory productFactory = null;
        switch (name) {
            case "华为":
                productFactory = new HuaWeiFactoryImpl();
                break;
            case "小米":
                productFactory = new XiaoMiFactoryImpl();
                break;
            default:
                return null;
        }

        Phone phone = productFactory.createPhone();
        if (phone != null) {
            return phone.callUp();
        }

        return null;
    }

    @ApiOperation("路由器")
    @GetMapping("router")
    public String router(String name) {
        ProductFactory productFactory = null;
        switch (name) {
            case "华为":
                productFactory = new HuaWeiFactoryImpl();
                break;
            case "小米":
                productFactory = new XiaoMiFactoryImpl();
                break;
            default:
                return null;
        }

        Router router = productFactory.createRouter();
        if (router != null) {
            return router.receiveNetworkData();
        }

        return null;
    }
}

源码下载

此隐藏内容仅限VIP查看升级VIP

测试

访问:http://localhost:8080/doc.html(当然,你用Postman也完全可以)

测试结果:

思考

咦?不是说抽象工厂是生产其他工厂的工厂吗?我怎么,还是在new 工厂类?并没有生产工厂呀?

实际上,我们可以将上边直接new 工厂类的方法用工厂模式中的简单工厂模式来写。即:传入想要的工厂,比如“小米”这个字符串,然后生产工厂的类来创建小米工厂。但是,这样的话,就像我们工厂模式介绍的那样,不如使用工厂方法模式。

2

评论2

请先

  1. 抽象工厂模式的例子,还是按照工厂方法模式写的?
    珠光2023 2023-09-18 0
    • 是的,最后有个“思考 ”,说明了为什么是这样写的。
      自学精灵 2023-09-18 0
显示验证码
没有账号?注册  忘记密码?

社交账号快速登录