使用java实现工厂方法模式

79 阅读1分钟

在简单工厂模式中,我们使用了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-不用改之前的代码,可以说是非常方便维护的人员了,不然在造宇宙飞船的时候,改了一行造汽车的代码,然后报错了。我就还得去学习造汽车来修复这个问题。非常耽误我造宇宙飞船的时间。