工厂模式不需要我们自己来创建产品(对象),需要什么产品直接向工厂要,当然要告知工厂我们想要什么,参数是必不可少的。
简单工厂模式
先来看简单工厂模式,这种模式是工厂把产品生产流水线都建好了,只需要我们向工厂索要就可以得到想要的产品,下面以汽车工厂生产汽车为例。
创建汽车接口,
/**
* 产品接口:车
* */
public interface Car {
public void run();
}
接下来创建奥迪汽车流水线,
/**
* 具体的产品:奥迪车
* */
public class AudiCar implements Car {
@Override
public void run() {
System.out.println("奥迪车在跑...");
}
}
当然也可以是创建其他类型的汽车,但是都必须要继承我们的Car接口,因为这是我们的汽车生产线。
接下来是我们的工厂,一个生产汽车的工厂。
/**
* 简单工厂:负责生产汽车
* */
public class SimpleFactory {
public static Car makeCar(String type) {
if ("audi".equals(type)) {
return new AudiCar();
}
return null;
}
}
测试类,我们直接调用工厂类的制作汽车方法来向工厂索要汽车,当然我们要告诉工厂我们想要什么品牌的汽车。
public class Test {
public static void main(String[] args) {
Car audi = SimpleFactory.makeCar("audi");
audi.run();
}
}
运行结果就是:
奥迪车在跑...
总结:
优点:从上面例子可以看出,简单工厂就是把所有的产品类都定义好了,接收不同的参数来决定创建不同的对象。
缺点 :如果我们需要新的产品,比如宝马汽车,那么我们就要修改工厂内部代码以增加流水线,违背开闭原则。
简单工厂优化:引入工厂接口
我们这次优化主要在工厂这方面,通过引入工厂接口,我们就可以通过不同的工厂来实现我们这个接口,来达到我们即想要不同品牌的汽车产品,又不修改原有工厂内部的代码。(横向拓展)。
汽车接口和汽车实现类和上面例子一样,这里就不做展示了,直接来看工厂接口(抽象工厂)
/**
* 抽象工厂:有一条汽车生产线
* */
public interface Factory {
Car makeCar();
}
那么如果我们需要奥迪汽车,只需要我们创建奥迪汽车的工厂来专门生产奥迪汽车。
/**
* 奥迪工厂:生产奥迪汽车
* */
public class AudiFactory implements Factory {
@Override
public Car makeCar() {
return new AudiCar();
}
}
这时,我们如果需要其他品牌的汽车,则只需要创建不同的工厂和具体的产品就可以了,方便拓展,比如再生产volvo汽车我们只需要这样做,
创建具体的汽车(继承汽车接口):
/**
* 具体的产品:沃尔沃车
* */
public class VolvoCar implements Car {
@Override
public void run() {
System.out.println("沃尔沃车在跑...");
}
}
创建具体的工厂(继承工厂接口):
/**
* Volvo工厂:生产Volvo汽车
* */
public class VolvoFactory implements Factory {
@Override
public Car makeCar() {
return new VolvoCar();
}
}
测试:
public class Test {
public static void main(String[] args) {
// Car audi = SimpleFactory.makeCar("audi");
// audi.run();
AudiFactory audiFactory = new AudiFactory();
Car audi = audiFactory.makeCar();
audi.run();
VolvoFactory volvoFactory = new VolvoFactory();
Car volvo = volvoFactory.makeCar();
volvo.run();
}
}
总结
有点:方便拓展
缺点:只有一条生产线,只能生产汽车。
进一步优化:可以生产飞机
我们再优化一下,可以让我们的工厂可以生产飞机,
首先定义飞机产品接口,
/**
* 产品接口:飞机
* */
public interface Plane {
public void fly();
}
然后是实际的飞机,
/**
* 具体飞机产品:C919飞机
* */
public class C919Plane implements Plane {
@Override
public void fly() {
System.out.println("c919飞机在飞...");
}
}
然后创建抽象工厂,拥有两条流水线,
/**
* 抽象工厂:有一条汽车生产线
* 增加一条飞机生产线
* */
public interface Factory {
Car makeCar();
Plane makePlane();
}
假设我们现在有需求,需要奥迪汽车和C919飞机,创建我们的实际的工厂来生产这两种产品,
/**
* 一个具体的工厂:生产奥迪车和C919飞机
* */
public class OneRealFactory implements Factory {
@Override
public Car makeCar() {
return new AudiCar();
}
@Override
public Plane makePlane() {
return new C919Plane();
}
}
测试:
public class Test {
public static void main(String[] args) {
OneRealFactory oneRealFactory = new OneRealFactory();
Car car = oneRealFactory.makeCar();
car.run(); // 奥迪车在跑...
Plane plane = oneRealFactory.makePlane();
plane.fly(); // c919飞机在飞...
}
}
总结:
优点:可以生产不同类型不同品牌的产品,可拓展性比较强。
缺点:当我们需要增加不同类型的产品时,如帆船,则需要修改所有的工厂类。