我在尝试完成需要使用策略和复合模式的实践时遇到了真正的麻烦。我正在尝试创建一个车辆集合,这些车辆可以根据它们所在的表面具有不同的行为。但是,这些车辆在表面上可能有不止一种行为 - 例如,如果天气条件设置为下雪和下雨,它们可能同时进行雪地行驶和雨天行驶。
我有一个名为 AbstractVehicle 的类,它有两个具体的子类,Car 和 Boat。
然后我有一个名为 IBehaviour 的界面。实现此接口的是两个抽象类,称为 LandBehaviour 和 WaterBehaviour(它们是复合模式的顶层)。它们中的每一个都有一个子类的集合。只关注 LandBehaviour,它的子类是 SnowBehaviour、StandardBehaviour 和其他一些,包括 LandAssembly。
我的想法是我将把复合材料的上层代码放在 LandBehaviour 中。然后,每个具体的子类将具有复合的添加、删除和列出部分的空实现,其中 LandAssembly 类包含实际将各种行为组合在一起所需的代码。
这是为了产生这样的结果,例如,一辆汽车可以同时具有 StandardBehaviour 和 SnowBehaviour。
我没有发布大量代码(而且有很多),而是希望对我正在尝试实现的基本结构提供一些反馈。我现在遇到了一些错误,例如空指针异常,而不是花很长时间尝试修复它们,我想了解项目的布局是否一开始就正确。
编辑:添加代码 - 生成空指针异常
这是我的 AbstractVehicle 类:
public AbstractVehicle (IBehaviour behaviourIn) {
behaviour = behaviourIn;
}
public void setBehaviour(IBehaviour ib) {
behaviour = ib;
}
public IBehaviour getBehaviour() {
return behaviour;
}
public void move() {
behaviour.ensureCorrectBehaviour();
}
汽车子类:
public Car () {
super(new StandardBehaviour());
}
IBehaviour 界面:
public interface IBehaviour {
public void ensureCorrectBehaviour();
}
LandBehaviour 抽象类:
public void ensureCorrectBehaviour() {
}
public ILandBehaviour () {
}
private ILandBehaviour landBehaviour;
public ILandBehaviour (ILandBehaviour landBehaviour) {
this.landBehaviour = landBehaviour;
}
public ILandBehaviour getBehaviour() {
return landBehaviour;
}
public abstract void addBehaviour(ILandBehaviour behaviour);
public abstract void removeBehaviour(ILandBehaviour behaviour);
public abstract ILandBehaviour[] getBehaviours();
具体行为子类 (RacingBehaviour) 的示例:
public RacingBehaviour(ILandBehaviour landBehaviour) {
super(landBehaviour);
}
public RacingBehaviour() {}
@Override
public void ensureCorrectBehaviour() {
System.out.println("Vehicle is racing.");
}
public void addBehaviour(ILandBehaviour behaviour) {}
public void removeBehaviour(ILandBehaviour behaviour) {}
public ILandBehaviour[] getBehaviours() {
return null;
}
最后是 LandAssembly 类:
public class LandAssembly extends ILandBehaviour {
private List<ILandBehaviour> behaviours;
public LandAssembly(ILandBehaviour landBehaviour) {
super(landBehaviour);
behaviours = new ArrayList<ILandBehaviour>();
}
public LandAssembly() {}
public void addBehaviour(ILandBehaviour behaviour) {
behaviours.add(behaviour);
}
public void removeBehaviour(ILandBehaviour behaviour) {
behaviours.remove(behaviour);
}
public ILandBehaviour[] getBehaviours() {
return behaviours.toArray(new ILandBehaviour[behaviours.size()]);
}
}
我正在使用这个跑步者:
AbstractVehicle aCar = new Car(120);
aCar.move();
ILandBehaviour snow = new SnowBehaviour();
ILandBehaviour racing = new RacingBehaviour();
ILandBehaviour as = new LandAssembly();
as.addBehaviour(snow);
as.addBehaviour(racing);
在我实施复合材料之前,一切都很好。我能够使用客户端创建一辆新车,调用它的 move() 方法,然后改变它的行为,再次调用 move() 并查看差异。然而,我知道我现在有点将 ensureCorrectBehaviour() 方法留在复合模式的实现中,这显然是错误的。我也知道,在这样做之后, Car 构造函数的“新”部分不起作用——我必须为每个行为添加一个空构造函数。
我可以在我创建的代码中看到明显的问题,我只是不太明白如何解决它们。