工厂模式

一、简单工厂

简单工厂的意图很简单,就是当用户想要一个产品的时候,可以直接从工厂里把产品拿出来,而不需要自己new一个。

首先创建一个Car类:

1
2
3
4
5
6
7
package factory;

public class Car {
public void go() {
System.out.println("Car go wuwuwu...");
}
}

然后在main函数里开车,启动,wuwuwu…

1
2
3
4
5
6
7
8
package factory;

public class Main {
public static void main(String[] args) {
Car c = new Car();
c.go();
}
}

但是现在忽然想要开飞机,最简单的想法是再建立一个飞机类,飞机飞呀飞,xiuxiuxiu…

1
2
3
4
5
6
7
package factory;

public class Plane {
public void go() {
System.out.println("Plane go xiuxiuxiu...");
}
}

更改main函数的代码即可…略…

However,此时我又想要开火车,这时候又要改变main代码,很麻烦,有没有比较好的方法呢?

所以创建一个Moveable的接口,里面有一个方法叫go(),然后让car、plane等交通工具类都去implement这个接口

1
2
3
public interface Moveable {
void go();
}

这样在main里就可以直接使用了:

1
2
3
4
5
6
7
8
package factory;

public class Main {
public static void main(String[] args) {
Moveable plane = new Plane();
plane.go();
}
}

好,通过上述代码实现了随意定制交通工具了,但如果想要任意定制这个交通工具的生产过程呢?我们把生产新的交通工具的过程,交给一个工厂,这个工厂有很多类型,先考虑简单工厂。

1
2
3
4
5
6
7
8
9
10
11
package factory;

public class VehicleFactory {
public Car createCar(){
return new Car();
}

public Plane createPlane(){
return new Plane();
}
}

然后在main函数里调用的时候,就不需要自己new一个交通工具出来了,直接交给VehicleFactory去做就行。

1
2
3
4
5
6
7
public class Main {
public static void main(String[] args) {
VehicleFactory f = new VehicleFactory();
Moveable c = f.createCar();
c.go();
}
}

这种方式很简单,但是可扩展性很差,因为每次想要新添加一个交通工具,都需要更改工厂代码。不符合开闭原则。那么干脆对每一种商品都构建一种工厂吧,这样就引入了第二种——工厂方法。

二、工厂方法

用来生产同一等级结构中的固定产品,支持增加任意产品,不需要覆盖原有代码。简而言之就是每一种Vehicle都有一个工厂。

首先建立一个接口VehicleFactory

1
2
3
public interface VehicleFactory {
Vehicle getVehicle;
}

然后建立每一种Vehicle的工厂,举个例子,比如CarFactory

1
2
3
4
5
6
public class CarFactory implements VehicleFactory {
@Override
public Vehicle getVehicle() {
return new Car();
}
}

(其余代码略)

这样每次使用的时候只需要在main里new一个对应的工厂就可以了

1
2
Car c = new CarFactory().getVehicle();
Plane p = new PlaneFactory().getVehicle();

三、抽象工厂

有一个超级工厂,这个超级工厂是用来生产工厂的工厂(好绕,感觉像在说绕口令QAQ)

直接看例子吧

这是一个抽象的超级工厂,可以看到里面不仅有创建食物,也能创建交通工具,还能创建武器(也就是抽象工厂里是抽象产品)

1
2
3
4
5
public abstract class AbstractFactory {
abstract Food createFood();
abstract Vehicle createVehicle();
abstract Weapon createWeapon();
}

然后每一种类别又有自己的工厂,比如modenFactory,就是可以创建现代世界的食物、交通工具、武器(这是具体工厂,具体工厂里生产具体产品)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ModernFactory extends AbstractFactory{
@Override
Food createFood(){
return new Bread();
}

@Override
Vehicle createVehicle(){
return new Car();
}

@Override
Weapon createWeapon() {
return new AK47();
}
}

(Bread、Car、AK47类就是具体产品类,代码略)

比如我们的magicFactory,就是魔法世界的食物、交通工具和武器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MagicFactory extends AbstractFactory{
@Override
Food createFood(){
return new Mushroom();
}

@Override
Vehicle createVehicle(){
return new Car();
}

@Override
Weapon createWeapon() {
return new AK47();
}
}

下面是Main的示例:

1
2
3
4
5
6
7
8
9
10
11
public class Main {
public static void main(String[] args) {
AbstractFactory f = new ModernFactory();
Vehicle c = f.createVehicle();
c.go();
Weapon w = f.createWeapon();
w.shoot();
Food fd = f.createFood();
fd.printName();
}
}

简而言之就是一个超级工厂,然后超级工厂下面有大类的工厂(具体工厂),每个大类的工厂可以生产自己类别独有的商品,然后同一类具体的产品均有一个共同的interface需要实现。

抽象工厂模式包含以下几个核心角色:

  • 抽象工厂(Abstract Factory):声明了一组用于创建产品对象的方法,每个方法对应一种产品类型。抽象工厂可以是接口或抽象类。
  • 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建具体产品对象的实例。
  • 抽象产品(Abstract Product):定义了一组产品对象的共同接口或抽象类,描述了产品对象的公共方法。
  • 具体产品(Concrete Product):实现了抽象产品接口,定义了具体产品的特定行为和属性。

当超级工厂里的具体工厂的类别只有一个时,其实就退化成了简单工厂。同样的,这种方式和简单工厂一样不满足开闭原则