工厂模式的作用
刚接触和使用工厂模式的时候,我心中一直有个疑惑,工厂模式有什么用?不使用的工厂模式的时候,我们需要知道具体类名字,使用了工厂模式之后我们仍然需要知道工厂类,最多是吧new对象时的构造函数和参数屏蔽了而已,为什么要做这样一步吃力而不讨好的工作?
带着这个疑惑我查阅了网上大量的资料,对工厂模式的作用有了更深的认识。
首先我们需要设置模式的一个重要的原则:开放封闭原则(Open Closed Principle),具体的解释是,对程序的扩展是开放的,对程序的修改是关闭的,如果需要增加功能,则只能以添加的形式修改,并不能改变原有的代码。
简单工厂
我们经常会遇到一些功能类似的类,所以我们的思路是对其进行抽象,使用接口暴露公共的地方,使用抽象类来提供公共的实现。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34//接口的命令 建议以I开头
public interface IProduct {
void print(); // 这是要暴露的方法
}
public abstract class AbstractProduct implements IProduct {
protected void printBefore(){
System.out.println("before print"); // 这里所公共的实现
}
}
public class AProduct extends AbstractProduct {
private String name;
public AProduct(String name){
this.name = name;
}
@Override
public void print() {
this.printBefore();
System.out.println("print A >>>"+name);
}
}
public class BProduct extends AbstractProduct {
private String name;
public BProduct(String name){
this.name = name;
}
@Override
public void print() {
this.printBefore();
System.out.println("print B >>>"+name);
}
}
此时有一个问题,如果这些类似的类非常多会导致这些类的实例化成了一个问题,每个类的构造参数还不一样,每次new对象非常的麻烦,我们此时就可以把它封装成简单工厂。1
2
3
4
5
6
7
8
9
10
11public class SimpleFactory {
public static IProduct getProduct(String name){
if("A".equals(name)){
return new AProduct(name);
}else if("B".equals(name)){
return new BProduct(name);
}else{
throw new IllegalArgumentException();
}
}
}
运用简单工厂模式,小伙伴有没有发现一个优点。假如你的项目中new了几十次某个对象,有些new的操作还比较隐蔽,几个月之后,这个类的构造方法被修改了,多了一个参数,那你是不是得找到这几十个地方修改,重复劳动了几十次,如果你使用了工厂模式,你只需要改一次就行了。
工厂方法
看到简单工厂的实现,我们可以发现,简单工厂其实并不符合开闭原则,每次添加新的实现类的时候,需要修改简单工厂里面的代码(如果是工厂类和业务类是两个小伙伴分开写的,那不是要花很多时间来沟通…),所以就有工厂方法模式,其原理就是对简单工厂也进行抽象。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public interface IFactory {
IProduct getProduct();
}
public class AFactory implements IFactory {
@Override
public IProduct getProduct() {
return new AProduct(AProduct.class.getName());
}
}
public class BFactory implements IFactory {
@Override
public IProduct getProduct() {
return new BProduct(BProduct.class.getName());
}
}
抽象工厂
看了工厂方法模式,突然发现有些糟糕了,因为代码变得很多了,因为功能类似的产品我们进行 2 层抽象,针对每个产品我们还抽象出了 2 层的工厂类。但是我们在某个具体的业务场景中,不单单是只实例化一个类啊。举一个例子,在游戏中,我们要一个战士配装备,首先我们需要配一把枪械(枪械有很多,步枪,狙击枪等,使用问题 1 进行抽象),但是配了枪械之后,我们还需要配子弹啊(继续使用问题 1 的方法进行抽象),好了,现在可以抽象出 2 层的工厂类了,针对现在的情况我们是不是可以让一个工厂既生产枪械,又生产子弹呢? 这就是抽象工厂模式。简单来说,可以把有一些有联系或者相近的产品,放到一个工厂去生产,没有必要单独再开一个工厂了。
假设前面所例举的AProduct类是手枪子弹。BProduct类是步枪子弹。
现在新增了,A2Product类手枪,B2Peoduct类步枪,他们都实现同一接口。
此时我们就可以吧AProduct和A2Product放在一个工厂中创建。同理B也是。1
2
3
4
5
6
7//抽象工厂类
public abstract class AbstractCreator {
//枪产品家族
public abstract AbstractProductA createProductA();
//子弹产品家族
public abstract AbstractProductB createProductB();
}
有N个产品族,在抽象工厂类中就应该有N个创建方法。1
2
3
4
5
6
7
8
9
10
11手枪的实现类
public class Creator1 extends AbstractCreator {
//手枪子弹
public AbstractProductA createProductA() {
return new ProductA1();
}
//手枪
public AbstractProductA2 createProductA2() {
return new ProductA2();
}
}
1 | 步枪的实现类 |
抽象工厂仅仅是工厂方法的复杂化,保存了多个new,只有在大工程才用的上。
我们在学习设计模式的时候,不能过分的套用设计模式去编码,很多设计模式是有缺陷的,我们要做到取长补短,不能过分的设计。在不适当的场景运用设计模式势必发挥不了他的作用,一般模式都是用来解耦 、便于扩展、便于维护的,我觉得不必拘泥于哪一种模式,只要能处理好业务的模式就是好模式,借用某位大神的话:模式本天成,妙手偶得之。粹然无疵瑕,岂复须人为。
参考:1
2
3https://www.zhihu.com/question/24843188
https://blog.csdn.net/qq_25827845/article/details/52503884
https://blog.csdn.net/singwhatiwanna/article/details/17428923