简介
说明
本文用示例介绍Java中的抽象工厂模式的用法。
抽象工厂模式:用来生产其他工厂的工厂。
适用场景
抽象工厂适用于多个品牌、多种产品类型的情况
优点
管理多个品牌、多个类型时,很方便。
缺点
增加新的产品类型时比较麻烦。
源码中的应用
- Spring中IOC容器创建/管理Bean对象
- 反射中Class对象的newInstance方法
- JDBC中的Connection对象的获取
- JDK中Calendar的getInstance方法
实例
需求:如上边“适用场景”所示,提供小米和华为两个品牌,手机和路由器两种类型。
最终结果的类图
产品
手机
手机产品(接口)
有这些方法:开机、关机、打电话、发短信。
package org.example.abstracts.product;
public interface IPhoneProduct {
void start();
void shutdown();
void callUp();
void sendSMS();
}
小米手机工厂(实现类)
package org.example.abstracts.product;
public class XiaomiPhone implements IPhoneProduct{
@Override
public void start() {
System.out.println("小米手机:开机");
}
@Override
public void shutdown() {
System.out.println("小米手机:关机");
}
@Override
public void callUp() {
System.out.println("小米手机:打电话");
}
@Override
public void sendSMS() {
System.out.println("小米手机:发短信");
}
}
华为手机工厂(实现类)
package org.example.abstracts.product;
public class HuaweiPhone implements IPhoneProduct{
@Override
public void start() {
System.out.println("华为手机:开机");
}
@Override
public void shutdown() {
System.out.println("华为手机:关机");
}
@Override
public void callUp() {
System.out.println("华为手机:打电话");
}
@Override
public void sendSMS() {
System.out.println("华为手机:发短信");
}
}
路由器
路由器产品(接口)
有这些方法:开机、关机、打开wifi、设置
package org.example.abstracts.product;
public interface IRouterProduct {
void start();
void shutdown();
void openWifi();
void setting();
}
小米路由器产品(实现类)
package org.example.abstracts.product;
public class XiaomiRouter implements IRouterProduct{
@Override
public void start() {
System.out.println("小米路由器:开机");
}
@Override
public void shutdown() {
System.out.println("小米路由器:关机");
}
@Override
public void openWifi() {
System.out.println("小米路由器:打开wifi");
}
@Override
public void setting() {
System.out.println("小米路由器:设置");
}
}
华为路由器产品(实现类)
package org.example.abstracts.product;
public class HuaweiRouter implements IRouterProduct{
@Override
public void start() {
System.out.println("华为路由器:开机");
}
@Override
public void shutdown() {
System.out.println("华为路由器:关机");
}
@Override
public void openWifi() {
System.out.println("华为路由器:打开wifi");
}
@Override
public void setting() {
System.out.println("华为路由器:设置");
}
}
工厂
工厂(接口)
package org.example.abstracts.factory;
import org.example.abstracts.product.IPhoneProduct;
import org.example.abstracts.product.IRouterProduct;
public interface IProductFactory {
IPhoneProduct phoneProduct();
IRouterProduct routerProduct();
}
小米工厂(实现类)
package org.example.abstracts.factory;
import org.example.abstracts.product.IPhoneProduct;
import org.example.abstracts.product.IRouterProduct;
import org.example.abstracts.product.XiaomiPhone;
import org.example.abstracts.product.XiaomiRouter;
public class XiaomiFactory implements IProductFactory{
@Override
public IPhoneProduct phoneProduct() {
return new XiaomiPhone();
}
@Override
public IRouterProduct routerProduct() {
return new XiaomiRouter();
}
}
华为工厂(实现类)
package org.example.abstracts.factory;
import org.example.abstracts.product.HuaweiPhone;
import org.example.abstracts.product.HuaweiRouter;
import org.example.abstracts.product.IPhoneProduct;
import org.example.abstracts.product.IRouterProduct;
public class HuaweiFactory implements IProductFactory{
@Override
public IPhoneProduct phoneProduct() {
return new HuaweiPhone();
}
@Override
public IRouterProduct routerProduct() {
return new HuaweiRouter();
}
}
测试
package org.example.abstracts;
import org.example.abstracts.factory.HuaweiFactory;
import org.example.abstracts.factory.IProductFactory;
import org.example.abstracts.factory.XiaomiFactory;
import org.example.abstracts.product.IPhoneProduct;
import org.example.abstracts.product.IRouterProduct;
public class Consumer {
public static void main(String[] args) {
IProductFactory xiaomiFactory = new XiaomiFactory();
IPhoneProduct xiaomiPhoneProduct = xiaomiFactory.phoneProduct();
xiaomiPhoneProduct.start();
IProductFactory huaweiFactory = new HuaweiFactory();
IRouterProduct iRouterProduct = huaweiFactory.routerProduct();
iRouterProduct.openWifi();
}
}
执行结果
小米手机:开机
华为路由器:打开wifi
思考
上边“实例(初版)”,我发现,咦?不是说抽象工厂是生产其他工厂的工厂吗?我怎么,还是在new 工厂类?并没有生产工厂呀?
实际上,我们可以将上边直接new 工厂类的方法用 工厂模式 中的简单工厂模式来写。即:传入想要的工厂,比如“小米”这个字符串,然后生产工厂的类来创建小米工厂。但是,这样的话,就像我们工厂模式介绍的那样,不如使用工厂方法模式。而,本处“实例(初版)”就是用的,工厂方法模式来创建工厂类。
其他网址
【狂神说Java】通俗易懂的23种设计模式教学(停更)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili