工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
工厂模式提供了一种将对象的实例化过程封装在工厂类中的方式。通过使用工厂模式,可以将对象的创建与使用代码分离,提供一种统一的接口来创建不同类型的对象。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
工厂模式可以分为三类:简单工厂模式(静态工厂模式)、工厂方法模式 和 抽象工厂模式。
其中简单工厂模式,严格上来说,不属于23设计模式之一,因为它违背了开闭原则,更好的是看作为一种编程方式。
本篇中会介绍三种工厂的使用,也就是
日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
等等。。。
下面我们模拟手机工厂生产手机。。。
实现了抽象工厂接口,负责实际创建具体产品的对象。
简单工厂包含如下角色:
模拟手机工厂生产手机。
我们需要定义一个抽象手机产品,定义手机产品的品牌和颜色两个方法
/**
* 手机产品抽象类
*
* @author jiangkd
* @date 2023/7/28 14:03:15
*/
public abstract class AbstractPhone {
/**
* 手机品牌
*/
public abstract void brand();
/**
* 手机颜色
*/
public abstract void color();
}
然后有两个具体产品,一加和真我,哈哈哈
/**
* 具体手机产品, 一加手机
*
* @author jiangkd
* @date 2023/7/28 14:06:17
*/
@Slf4j
public class YijiaPhone extends AbstractPhone {
@Override
public void brand() {
log.info("品牌, 一加手机!!!");
}
@Override
public void color() {
log.info("黑色!!!");
}
}
/**
* 具体手机产品, 真我手机
*
* @author jiangkd
* @date 2023/7/28 14:07:27
*/
@Slf4j
public class ZhenwoPhobe extends AbstractPhone {
@Override
public void brand() {
log.info("品牌, 真我手机!!!");
}
@Override
public void color() {
log.info("白色!!!");
}
}
产品有了,现在我们创建一个手机工厂,可以根据不同参数创建不同品牌手机
/**
* 手机产品的工厂
*
* @author jiangkd
* @date 2023/7/28 14:09:50
*/
public class PhoneFactory {
/**
* 具体如何产生一个产品的对象,是由具体的工厂类实现的
*
* 注意, 这里是静态方法
*
* @param clazz
* @return AbstractPhone
* @throws Exception e
*/
public static AbstractPhone createPhone(Class clazz) throws Exception {
// 全限定类名
final String name = clazz.getName();
// 根据反射, 创建具体产品对象
return (AbstractPhone) Class.forName(name).newInstance();
}
/**
* 当前方法其实和createPhone方法是一样的作用, 两个方法用哪个都可以
*
* 注意, 这里是静态方法
*
* @param brand 根据参数区分创建哪个具体产品
* @return AbstractPhone
*/
public static AbstractPhone createPhone2(String brand) throws Exception {
if (CharSequenceUtil.equals("yijia", brand)) {
return new YijiaPhone();
} else if (CharSequenceUtil.equals("zhenwo", brand)) {
return new ZhenwoPhobe();
} else {
throw new Exception("参数异常!!!");
}
}
}
测试一下
/**
* @author jiangkd
* @date 2023/7/28 14:17:25
*/
@Slf4j
public class DemoTest {
public static void main(String[] args) throws Exception {
// 创建一加手机
AbstractPhone yijiaPhone = PhoneFactory.createPhone(YijiaPhone.class);
yijiaPhone.brand();
yijiaPhone.color();
log.info("--------------------------------");
yijiaPhone = PhoneFactory.createPhone2("yijia");
yijiaPhone.brand();
yijiaPhone.color();
log.info("--------------------------------");
// 创建真我手机
AbstractPhone zhenwoPhone = PhoneFactory.createPhone(ZhenwoPhobe.class);
zhenwoPhone.brand();
zhenwoPhone.color();
log.info("--------------------------------");
zhenwoPhone = PhoneFactory.createPhone2("zhenwo");
zhenwoPhone.brand();
zhenwoPhone.color();
}
}
运行结果如下:
14:19:59.846 [main] INFO demo.basic.example.design_patterns.gcms.jdgcms.YijiaPhone - 品牌, 一加手机!!!
14:19:59.851 [main] INFO demo.basic.example.design_patterns.gcms.jdgcms.YijiaPhone - 黑色!!!
14:19:59.851 [main] INFO demo.basic.example.design_patterns.gcms.jdgcms.DemoTest - --------------------------------
14:19:59.882 [main] INFO demo.basic.example.design_patterns.gcms.jdgcms.YijiaPhone - 品牌, 一加手机!!!
14:19:59.882 [main] INFO demo.basic.example.design_patterns.gcms.jdgcms.YijiaPhone - 黑色!!!
14:19:59.882 [main] INFO demo.basic.example.design_patterns.gcms.jdgcms.DemoTest - --------------------------------
14:19:59.882 [main] INFO demo.basic.example.design_patterns.gcms.jdgcms.ZhenwoPhobe - 品牌, 真我手机!!!
14:19:59.882 [main] INFO demo.basic.example.design_patterns.gcms.jdgcms.ZhenwoPhobe - 白色!!!
14:19:59.882 [main] INFO demo.basic.example.design_patterns.gcms.jdgcms.DemoTest - --------------------------------
14:19:59.882 [main] INFO demo.basic.example.design_patterns.gcms.jdgcms.ZhenwoPhobe - 品牌, 真我手机!!!
14:19:59.882 [main] INFO demo.basic.example.design_patterns.gcms.jdgcms.ZhenwoPhobe - 白色!!!
其实可以看出来,这里我们只有两个具体的手机产品,简答(静态)工厂模式还是很方便的,但你有没有发现,如果现在我陆陆续续追加其他具体产品 红米!努比亚!荣耀!那么我就要陆陆续续三次修改手机工厂类(追加具体产品不算修改,是扩展功能)的功能,这显然不符合java设计模式的六大原则-开闭原则。
那不如我们把工厂拆开,每个工厂只生产一种具体的手机产品,这样如果我需要增加一个红米,就只需要添加一个红米工厂和一个红米产品类就可以了,这就是接下来要演示的工厂方法模式
简单工厂模式确实很方便,但是每次新增一个手机产品都需要改动整个工厂的原有代码,现在使用工厂方法模式改造一下。
抽象手机产品AbstractPhone 和 两个具体的手机产品(一加,真我)不变,依然如上。
工厂类PhoneFactory不要了,我们需要重新创建工厂类。
现在我们首先创建一个抽象工厂类,用来生产AbstractPhone
/**
* 定义产品的抽象工厂类
*
* @author jiangkd
* @date 2023/7/28 14:43:04
*/
public abstract class AbstractPhoneFactory {
/**
* 构建产品, 具体实现交给子类
*
* @return AbstractPhone
*/
abstract AbstractPhone createPhone();
}
然后分别是一加手机和真我手机的两个具体工厂实现类,每个实现类针对一个具体手机品牌的生产
/**
* 具体产品一加手机的工厂实现类
*
* @author jiangkd
* @date 2023/7/28 14:44:53
*/
public class YijiaPhoneFactory extends AbstractPhoneFactory {
@Override
AbstractPhone createPhone() {
return new YijiaPhone();
}
}
/**
* 具体产品真我手机的工厂实现类
*
* @author jiangkd
* @date 2023/7/28 14:45:35
*/
public class ZhenwoPhoneFactory extends AbstractPhoneFactory {
@Override
AbstractPhone createPhone() {
return new ZhenwoPhobe();
}
}
测试一下
/**
* @author jiangkd
* @date 2023/7/28 14:46:16
*/
@Slf4j
public class DemoTest {
public static void main(String[] args) {
// 生产一加手机
final AbstractPhoneFactory yijiaPhoneFactory = new YijiaPhoneFactory();
final AbstractPhone yijiaPhone = yijiaPhoneFactory.createPhone();
yijiaPhone.brand();
yijiaPhone.color();
log.info("--------------------------------");
// 生产真我手机
final AbstractPhoneFactory zhenwoPhoneFactory = new ZhenwoPhoneFactory();
final AbstractPhone zhenwoPhone = zhenwoPhoneFactory.createPhone();
zhenwoPhone.brand();
zhenwoPhone.color();
}
}
运行结果如下:
14:48:22.596 [main] INFO demo.basic.example.design_patterns.gcms.YijiaPhone - 品牌, 一加手机!!!
14:48:22.598 [main] INFO demo.basic.example.design_patterns.gcms.YijiaPhone - 黑色!!!
14:48:22.598 [main] INFO demo.basic.example.design_patterns.gcms.gcffms.DemoTest - --------------------------------
14:48:22.599 [main] INFO demo.basic.example.design_patterns.gcms.ZhenwoPhobe - 品牌, 真我手机!!!
14:48:22.599 [main] INFO demo.basic.example.design_patterns.gcms.ZhenwoPhobe - 白色!!!
现在我们如果想要加一个红米手机,只需要创建具体红米产品和对应的工厂类就可以了
/**
* 具体手机产品 红米
*
* @author jiangkd
* @date 2023/7/28 14:51:09
*/
@Slf4j
public class HongmiPhone extends AbstractPhone {
@Override
public void brand() {
log.info("品牌, 红米手机!!!");
}
@Override
public void color() {
log.info("红色!!!");
}
}
/**
* 红米手机工厂实现类
*
* @author jiangkd
* @date 2023/7/28 14:52:04
*/
public class HongmiPhoneFactory extends AbstractPhoneFactory {
@Override
AbstractPhone createPhone() {
return new HongmiPhone();
}
}
测试
/**
* @author jiangkd
* @date 2023/7/28 14:46:16
*/
@Slf4j
public class DemoTest {
public static void main(String[] args) {
// 生产一加手机
final AbstractPhoneFactory yijiaPhoneFactory = new YijiaPhoneFactory();
final AbstractPhone yijiaPhone = yijiaPhoneFactory.createPhone();
yijiaPhone.brand();
yijiaPhone.color();
log.info("--------------------------------");
// 生产真我手机
final AbstractPhoneFactory zhenwoPhoneFactory = new ZhenwoPhoneFactory();
final AbstractPhone zhenwoPhone = zhenwoPhoneFactory.createPhone();
zhenwoPhone.brand();
zhenwoPhone.color();
log.info("--------------------------------");
// 生产红米手机
final AbstractPhoneFactory hongmiPhoneFactory = new HongmiPhoneFactory();
final AbstractPhone hongmiPhone = hongmiPhoneFactory.createPhone();
hongmiPhone.brand();
hongmiPhone.color();
}
}
执行结果
14:53:43.272 [main] INFO demo.basic.example.design_patterns.gcms.YijiaPhone - 品牌, 一加手机!!!
14:53:43.274 [main] INFO demo.basic.example.design_patterns.gcms.YijiaPhone - 黑色!!!
14:53:43.274 [main] INFO demo.basic.example.design_patterns.gcms.gcffms.DemoTest - --------------------------------
14:53:43.276 [main] INFO demo.basic.example.design_patterns.gcms.ZhenwoPhobe - 品牌, 真我手机!!!
14:53:43.276 [main] INFO demo.basic.example.design_patterns.gcms.ZhenwoPhobe - 白色!!!
14:53:43.276 [main] INFO demo.basic.example.design_patterns.gcms.gcffms.DemoTest - --------------------------------
14:53:43.276 [main] INFO demo.basic.example.design_patterns.gcms.HongmiPhone - 品牌, 红米手机!!!
14:53:43.276 [main] INFO demo.basic.example.design_patterns.gcms.HongmiPhone - 红色!!!
符合开闭原则,不修改原来的功能,只是添加产品和工厂类就可以了。
细心的小伙伴又会问了,虽然不用在原基础功能上修改,但是如果还要添加10个品牌手机,岂不是要加10个产品类和10个工厂类,增加维护难度呀!是的,这就是工厂方法模式的弊端,增加系统的复杂度。
所以你可以看出,简单(静态)工厂和工厂方法模式,都是针对一类产品的生产,也就是这些工厂只生产同种类产品,同种类产品称为同等级产品。(工厂方法模式只考虑生产同等级的产品)
但实际上呢,现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。
这就是下面的抽象工厂模式了。。。,我们继续延申,现在老板发话了,生产手机的时候,顺便把耳机也生产出来吧
由于篇幅问题,继续查看java设计模式-工厂模式(下)