前言
简单工厂模式,虽然不在23种设计模式中。但是可以认为是工厂模式的一种特殊实现,并且在日常中使用广泛,所以还是值得我们去学习的。
定义
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,是一种创建型的设计模式,关注于实例对象创建。
由一个工厂对象通过判断传入的参数,决定创建出哪一种产品类的实例,将创建的细节透明化。
注意:简单工厂不属于GOF23种之一。
场景
在周一阳光明媚的上午,刚带上耳机,准备开始一天的工作,老板突然来到你身旁。
- 老板: xxx啊,听说你是学计算机的?
- 我:是的,学的是软件工程。
- 老板:那帮我组装一台苹果电脑出来吧,周五送到我办公桌上。
- 我:内心OS:修电脑,我也就认了,这竟然让我组装一台苹果电脑,你咋不上天呢?
- 老板:预算5000,记得不要超支了。
- 我:内心虽然波涛汹涌,但是还是说了声,好的老板。
于是我就立马打开chrome,上各大论坛搜索完美黑苹果配置,在初步确定好配置后,就开始上京东,开始选购CPU,主板,固态,内存,电源等配件。在经历了两天的等待,所有配件终于到齐以后,耗费九牛二虎之力,终于在周五前把电脑给组装好了。
可是呢没过多久,总经理也找我说让我帮他组一台苹果电脑,和老板同样的套路,我能咋办,我也很无耐,但是给的预算更低只有4000于是我也只能在原来的基础上缩减一下配置,勉强达到了要求。
我在想要是每个领导都这样,那我不是得凉凉啊,想到这里我暗自下定决心,对自己说我下次一定要拒绝他们。
优点
只需要知道产品的名称即可,就可以创建你所需要的对象,而无需知道其创建细节。
缺点
工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则,如果产品数量过多,维护将变得非常困难。
注意:使用反射和枚举可以避免频繁修改工厂类。
使用场景
- 将实例化过程非常复杂的类,通过工厂进行简化,方便业务方使用。
- 把创建对象的职责集中管理和控制。
小结
从上面的小故事可以简单的理解为:老板就是需求方,我就是工厂,老板只需要告诉我,他需要什么就好了,不管我如何实现。但是如果需要的产品变更了,我就只能做修改来满足要求。
UML模型
代码实例
BaseComputer
public abstract class BaseComputer {
/**
* 开机
*/
protected abstract void turnOn();
}
MacBookPro
public class MacBookPro extends BaseComputer {
@Override
protected void turnOn() {
System.out.println("MacBook Pro 开机了");
}
}
ThinkPad
public class ThinkPad extends BaseComputer {
@Override
protected void turnOn() {
System.out.println("Think Pad 开机了");
}
}
ComputerFactory
public class ComputerFactory {
/**
* 创建电脑
* @param name 名称
* @return 返回电脑
*/
public static BaseComputer create(String name){
if("mac".equals(name)){
return new MacBookPro();
}else if("thinkPad".equals(name)){
return new ThinkPad();
}else {
throw new IllegalArgumentException("无法创建"+name+"电脑。");
}
}
}
测试
public class Test {
public static void main(String[] args) {
BaseComputer mac = ComputerFactory.create("mac");
mac.turnOn();
BaseComputer thinkPad = ComputerFactory.create("thinkPad");
thinkPad.turnOn();
BaseComputer dell = ComputerFactory.create("dell");
dell.turnOn();
}
}
测试结果
MacBook Pro 开机了
Think Pad 开机了
Exception in thread "main" java.lang.IllegalArgumentException: 无法创建dell电脑。
at simple.factory.ComputerFactory.create(ComputerFactory.java:22)
at simple.factory.Test.main(Test.java:18)
重构ComputerFactory - Switch
对于ComputerFactory使用if的写法不是很优雅,对此我们可以改成使用switch语句。
注意:Java7以后的版本switch才支持字符串,Java7以前只支持int 、short 、byte 、char
public class ComputerFactory {
/**
* 创建电脑
* @param name 名称
* @return 返回电脑
*/
public static BaseComputer create(String name){
switch (name){
case "mac":
return new MacBookPro();
case "thinkPad":
return new ThinkPad();
default:
throw new IllegalArgumentException("无法创建"+name+"电脑。");
}
}
}
重构ComputerFactory - 反射
public class ComputerFactory {
/**
* 创建电脑
* @param name 名称
* @return 返回电脑
*/
public static BaseComputer create(String name) {
BaseComputer computer;
try {
computer = (BaseComputer) Class.forName(name).getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e ) {
throw new IllegalArgumentException("无法创建"+name+"电脑。");
}
return computer;
}
}
测试类
public class Test {
public static void main(String[] args) {
BaseComputer mac = ComputerFactory.create("simple.factory.MacBookPro");
mac.turnOn();
BaseComputer thinkPad = ComputerFactory.create("simple.factory.ThinkPad");
thinkPad.turnOn();
BaseComputer dell = ComputerFactory.create("simple.factory.Dell");
dell.turnOn();
}
}
重构ComputerFactory - 反射 + 枚举
public class ComputerFactory {
/**
* 创建电脑
* @param name 名称
* @return 返回电脑
*/
public static BaseComputer create(ComputerEnum name) {
BaseComputer computer;
try {
computer = (BaseComputer) name.getClazz().newInstance();
} catch (InstantiationException | IllegalAccessException e ) {
throw new IllegalArgumentException("无法创建"+name+"电脑。");
}
return computer;
}
}
电脑枚举类
public enum ComputerEnum {
/**
* 电脑枚举类
*/
MAC_BOOK_PRO(MacBookPro.class),
THINK_PAD(ThinkPad.class),
;
private Class clazz;
ComputerEnum(Class clazz) {
this.clazz = clazz;
}
public Class getClazz() {
return clazz;
}
}
测试类
public class Test {
public static void main(String[] args) {
BaseComputer mac = ComputerFactory.create(ComputerEnum.MAC_BOOK_PRO);
mac.turnOn();
BaseComputer thinkPad = ComputerFactory.create(ComputerEnum.THINK_PAD);
thinkPad.turnOn();
}
}
结尾
如果觉得对你有帮助,可以多多评论,多多点赞哦,也可以到我的主页看看,说不定有你喜欢的文章,也可以随手点个关注哦,谢谢。
我是不一样的科技宅,每天进步一点点,体验不一样的生活。我们下期见!