2019-08-09 | 设计模式 | UNLOCK

三种工厂模式

工厂模式

工厂方法模式:工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

工厂模式的缺点就是没次都会创建一个新的对象,无法实现单例。Spring的Ioc解决了这个问题。

一、简单工厂方法

有很多个类(ConcreteProduct)都实现了同一个接口(Product),不必在每用到子类的地方直接new 一个子类,这样不利于管理和维护。比如某个ConcreteProduct的名字变了,那么所有使用到这个类的地方都需要进行更改维护,使用简单工厂方法就不会存在这种情况:

示例:

1. Product接口

1
2
3
public interface Product {
Object action();
}

2. ConcreteProduct实现类

  • (1) GoodProduct
1
2
3
4
5
6
public class GoodProduct implements Product {
@Override
public Object action() {
return "good";
}
}
  • (2) BadProduct
1
2
3
4
5
6
public class BadProduct implements Product {
@Override
public Object action() {
return "bad";
}
}

3.简单工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ProductFactory {//简单工厂类
public static Product createProduct(String name){
Product product = null;
switch (name){
case "good":
product = new GoodProduct();
break;
case "bad":
product = new BadProduct();
break;
}
return product;
}
}

使用的时候就很简单了,只需要通过:

1
Product product = ProductFactory.createProduct("good");

即可得到一个GoodProduct示例,这样即使GoodProduct名字变量,使用的客户端也不必知道。

二、工厂方法

简单工厂方法的缺点就是需要不断的维护简单工厂类,随着实现子类的增多,简单工厂类会变得越来越臃肿,因此在很大程度上,简单工厂类具有很强的耦合性,还可以进行优化,那就是为每一个具体的ConcreteProduct都创建一个工厂类:

示例:

1.Product接口

同上

2.ConcreteProduct实现类

同上

3.Factory接口/抽象类

1
2
3
4
5
6
7
8
public abstract class Factory {
public abstract Product createProduct();

private void dosomething(){
Product product = createProduct();
product.action();//回调实现
}
}

如果使用了抽象类,还可以在工厂里面定义一些方法,用于实现回调。

4.ConcreteFactory实现类

  • GoodFactory
1
2
3
4
5
6
public class GoodFactory extends Factory {
@Override
public Product createProduct() {
return new GoodProduct();
}
}
  • BadFactory
1
2
3
4
5
6
public class BadFactory extends Factory {
@Override
public Product createProduct() {
return new BadProduct();
}
}

使用的时候需要先创建对应的工厂,那么创建具体的对象就转为创建了对应的工厂了。感觉是进行了耦合的转移,并没有解耦。不过可以通过反射的方式创建:

1
2
Factory badFactory = (Factory) Class.forName("com.design.factory.factorymethod.BadFactory").newInstance();
Product badP = badFactory.createProduct();

我感觉工厂方法模式最大的作用可能就是回调吧。

三、抽象工厂

抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。

抽象工厂模式用到了工厂方法模式来创建单一对象,AbstractFactory 中的 createProductA() 和 createProductB() 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂方法模式的定义。

至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要同时创建出这两个对象。

从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂方法模式使用了继承。

示例:

1.Product接口/抽象类/普通类-家族

  • ProductA
1
2
3
public interface ProductA {
Object actionA();
}
  • ProductB
1
2
3
public interface ProductB {
Object actionB();
}

2.ConcreteProduct实现类

  • GoodProductA
1
2
3
4
5
6
public class GoodProductA implements ProductA {
@Override
public Object actionA() {
return "good-A";
}
}
  • GoodProductB
1
2
3
4
5
6
public class GoodProductB implements ProductB {
@Override
public Object actionB() {
return "good-B";
}
}
  • BadProductA
1
2
3
4
5
6
public class BadProductA implements ProductA {
@Override
public Object actionA() {
return "bad-A";
}
}
  • BadProductB
1
2
3
4
5
6
public class BadProductB implements ProductB {
@Override
public Object actionB() {
return "bad-B";
}
}

3. AbstractFactory(抽象工厂)

创建对象的家族

1
2
3
4
abstract class AbstractFactory {
abstract ProductA createProductA();
abstract ProductB createProductB();
}

4.ConcreteFactory实现类

  • GoodFactory
1
2
3
4
5
6
7
8
9
10
11
public class GoodFactory extends AbstractFactory {
@Override
ProductA createProductA() {
return new GoodProductA();
}

@Override
ProductB createProductB() {
return new GoodProductB();
}
}
  • BadFactory
1
2
3
4
5
6
7
8
9
10
11
public class BadFactory extends AbstractFactory {
@Override
ProductA createProductA() {
return new BadProductA();
}

@Override
ProductB createProductB() {
return new BadProductB();
}
}

使用的时候,通过:

1
2
3
AbstractFactory af = new GoodFactory();//GoodFactory
Product pa = af.createProductA();//ProductA
Product pb = af.createProductB();//ProductB

可以创建不同的对象族。

比较

个人觉得这个区别在于产品,如果产品单一,最合适用工厂模式;如果有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。

再通俗深化理解下:工厂模式针对的是一个产品等级结构 ,抽象工厂模式针对的是面向多个产品等级结构的。

例子

用种蔬菜的例子来说明事实:

(1)最初的时候,由于规模小,只种植一种蔬菜,根菜类蔬菜,这个时候由于种植方式比较简单,采用简单工厂模式即可,主要目的是让工人轻松,下达工厂种植即可:

(2)但是随着种植厂的发展以及市场的需求,要增加一种蔬菜类型种植了,茎菜,由于茎菜根菜种植方式不一致,就需要两个专门的种植工厂来进行管理,那么就采用工厂模式来管理,一个工厂负责一种作物的种植,这个时候产品可以理解为仍然在一个层次。

(3)但是随着科技的发展,我们逐步要种植转基因非转基因食品了,在以前的蔬菜种类上又增加了一个层次,这个时候无法将其作为一个层次来解决,所以必须采用抽象工厂的方式来解决。

总结

在简单工厂模式下,工人要想到种植萝卜还是白菜,在工厂模式下,工人想到是种植根菜还是茎菜,而在抽象工厂模式下,则关心种植基因菜还是非基因菜

参考文章:

1.三种工厂模式的使用选择

2.Cyc-工厂模式(Simple Factory)

评论加载中