问题
小明需要一辆自行车去上班:
Bicycle bicycle = new Bicycle();
bicycle.riding();
要远距离出差,于是需要一辆汽车:
Car car = new Car();
car.drive();
对于小明来讲,对小明来讲有如下问题:
- 因为调用了具体交通工具类的具体方法,导致修改交通工具时需要修改大量代码。
- 小明需要亲自造车。
第一个问题可以将自行车和汽车抽象为抽象类或接口:Vehicle,然后将自行车和汽车实现该接口,因为他们的作用都是出行,于是:
public interface Vehicle {
void go();
}
public class Bicycle implements Vehicle {
@Override
public void go() {
riding();
}
}
此时小明就可以:
Vehicle vehicle = new Bicycle();
vehicle.go();
第一个问题解决了,至于第二个问题很容易想到简单工厂模式:
public class VehicleFactory {
public static Vehicle create(String type) {
if ("bicycle".equals(type)) {
return new Bicycle();
} else if ("car".equals(type)) {
return new Car();
} else {
return null;
}
}
}
于是,小明就可以这样来实现:
Vehicle vehicle = VehicleFactory.create("bicycle");
vehicle.go();
问题完美的解决了,一段时间之后,国外的客户需要小明驻场,汽车已经不能满足了,要换飞机,于是小明修改了工厂类:
public class VehicleFactory {
public static Vehicle create(String type) {
if ("bicycle".equals(type)) {
return new Bicycle();
} else if ("car".equals(type)) {
return new Car();
} else if ("plane".equals(type)) {
return new Plane();
} else {
return null;
}
}
}
每次扩展都需要修改工厂类,并不符合开闭原则。工厂类即负责对象的创建,又负责业务逻辑的处理,不符合单一职责原则。怎么优化呢?
每种产品创建一个工厂然后将所有工厂抽象为交通方式工厂抽象类或接口,客户端需要时直接从具体产品工厂获取,这样即实现了客户端不需要直接创建对象,又避免了当新增产品扩展时频繁修改工厂类。
代码
pubic interface Cehicle {
void go();
}
public class Bicycle implements Vehicle {
void go() {
// 自行车出行
}
}
public interface VehicleFactory{
create();
}
public class BicycleFactory implements VehicleFactory {
@Override
Vehicle create() {
return new Bicycle();
}
}
客户端小明就可以这样使用:
VehicleFactory vehicleFactory = new BicycleFactory();
Vehicle vehicle = vehicleFactory.create();
vehicle.go();
这样当扩展飞机时就可以直接创建PlaneFactory实现接口VehicleFactory、Plane实现接口Vehicle就可以了。
定义
在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。
父类VehicleFactory.create(),子类BicycleFactory.create()返回Bicycle,子类CarFactory.create()返回Car。也就是最终返回什么类型取决于使用的哪个子类。
使用场景
- 有多个同类产品,后续可能会扩展,不确定使用那个产品。