我使用了一个需要修补的库。我需要分叉它,因为不使用工厂设计模式。
库具有这样的结构:类 X 保存对其他类的引用,保存对其他类的引用和更多层。类层次结构是"树状"结构。
我寻找重构的最佳方法 - 足够灵活以防止人们分叉它。我找不到关于这个问题的任何最佳做法。
多年来,我通过"注入工厂"来解决它 - 工厂模式,其中父对象在工厂方法中被注入(DI)。我找不到有关这种方法的任何文档,我需要一些反馈(例如理论或可能的问题)。
我用 Car 的例子来描述它:
汽车- 有汽车内饰
- 汽车内饰有里程表
问题 – 无法创建自定义对象,尤其是里程表。
class Car {
CarInterior interior;
public Car() {
interior = new CarInterior();
}
}
class CarInterior {
Odometer odo;
public CasInterior(){
odo = new Odomether();
}
}
class Odometer {
public Odometer(){}
}
仅使用简单工厂方法模式的按书解决方案(具有有限的可扩展性)
class Car {
CarInterior interior;
public Car(CarFactory factory) {
interior = createInterior();
}
CarInterior createInterior() { return new CarInterior(); };
}
class CasInterior {
Odometer odo;
public CarInterior(){
odo = createOdometer();
}
CarInterior createOdometer() {
return new Odomether();
}
}
这种方法的主要问题
- 如果工厂方法需要参数,则该更改可能会给 lib 用户带来麻烦。因为扩展类应该更改方法定义。
小问题
- 如果我需要不同的里程表,我应该同时扩展汽车和汽车内饰
- 我需要分叉的库很少有"级别",所以这意味着许多级别的额外对象,直到我设法调用工厂方法。
可能的业务请求
里程表类的可能扩展#1:使用KM或英里
汽车对象应具有目标国家/地区。如果是在法国,则应使用公制单位。如果在美国 - 英里。 该业务请求可以通过以下方式实现:
- (重大更改)工厂方法 createOdometer() 获取参数:createOdometer(OdoUnits)
- (重大更改)工厂方法 createInterior() 获取参数:createInterior(OdoUnits) 或 createInterior(Country)
- 在更多级别的情况下(我的情况),需要更多更改
类的可能扩展#2:里程表值范围
- 0-220公里/小时
- 0-300公里/小时
- 等
类的可能扩展#3:里程表的颜色应与汽车的颜色相同
如果我们使用相同的方法,我们应该在方法中引入更多参数。以及更多的"代理"功能。
问题
那么这个问题的最佳实践是什么?在新需求到来时,我们如何避免/减少方法定义更改?
"Injecting Factory">
- 工厂方法采用一个附加参数 – 父对象。
- 里程表获取其工厂,获取 Car 对象并请求所有需要的数据以适应"汽车规格">
法典:
class CarFactory {
CarInterior createInterior(Car car) { return new CarInterior(car); }
Odometer createOdometer(CarInterior interior){ return new Odometer(interior); };
}
class Car {
CarFactory factory;
CarInterior interior;
public Car(CarFactory factory) {
this.factory = factory;
interior = factory.createInterior(this);
}
CarFactory getFactory(){ return factory; };
}
class CarInterior {
Car car;
Odometer odo;
public CarInterior(Car car){
this.car = car;
CarFactory factory = car.getFactory();
odo = factory.createOdometer( this );
}
}
class Odometer {
public Odometer(CarInterior interior) {
Car car = interior.getCar();
OdoUnits odoUnits = car.getTargetCountry().getUnits();
int maxEngineSpeed = car.getEngine().getTopSpeed;
Color color = car.getColor();
if (!car.isOptionColorOdometer())
color = DEFAULT_COLOR;
// etc
}
}