在简单工厂模式中,我们使用了Factory来创建对象,让调用者无需关心对象的创建细节,只需要输入想要的字符串就能获取到对应的对象。但是后续如果新增了一个Ship类,维护者需要去修改工厂类,去添加一个判断,这样非常麻烦,违背了开闭原则,一般来说,写好了的代码,我们都不希望去动他们了。那么有没有办法能够不动之前的代码前提下,新增一个Ship类,让调用者能够正常调用。
下面我们将使用工厂方法模式来实现这个需求。
1-交通工具类不变
abstract public class Vehicle {
//公共抽象方法
public abstract String getName();
}
public class Plane extends Vehicle {
private String name;
public Plane(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
public class Car extends Vehicle {
private String name;
public Car(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
2-新增一个抽象的工厂类Factory,并且将创建交通工具类的实现分别交给BenzFactory和BoeingFactory。
public abstract class Factory {
public abstract Vehicle buildVehicle();
}
public class BenzFactory extends Factory {
@Override
public Vehicle buildVehicle() {
return new Car("奔驰");
}
}
public class BoeingFactory extends Factory {
@Override
public Vehicle buildVehicle() {
return new Plane("波音");
}
}
3-在客户端调用时使用反射调用工厂创建交通工具类
@SneakyThrows
public static void main(String[] args) {
while (true){
Scanner scanner = new Scanner(System.in);
String code = scanner.nextLine();
//新增一个map用来映射调用代号和创建路径
Map<String, String> map = new HashMap<>();
map.put("car","com.BenzFactory");
map.put("plane","com.BoeingFactory");
Factory o = (Factory) Class.forName(map.get(code)).newInstance();
Vehicle vehicle = o.buildVehicle();
System.out.println(vehicle.getName());
}
}
4-完成了工厂方法模式改造之后,后续拓展就不用修改以前的代码了。如果我们新增了一个需求,客户需要一艘宇宙飞船,我们不用修改之前的代码也能实现这个需求。
4-1我们先来一个宇宙飞船类Ship并且继承Vehicle,再来一个SpaceXFactory类继承Factory。
public class Ship extends Vehicle{
private String name;
public Ship(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
public class SpaceXFactory extends Factory{
@Override
public Vehicle buildVehicle() {
return new Ship("宇宙飞船");
}
}
4-2然后在客户端浅浅的加一段映射,就能直接创建宇宙飞船了。
map.put("ship","com.SpaceXFactory");
5-不用改之前的代码,可以说是非常方便维护的人员了,不然在造宇宙飞船的时候,改了一行造汽车的代码,然后报错了。我就还得去学习造汽车来修复这个问题。非常耽误我造宇宙飞船的时间。