戦略と複合パターンを使用する必要がある実践を完了しようとすると、実際に問題が発生します。表面によって動作が異なる車両のコレクションを作成しようとしています。ただし、これらの車両は、表面上で複数の動作をする可能性があります。たとえば、気象条件が雪と雨に設定されている場合、雪のドライブと雨のドライブを同時に行うことができます。
私にはAbstractVehicleというクラスがあり、CarとBoatの2つの具体的なサブクラスがあります。
次に、IBehaviourというインターフェイスがあります。このインターフェースの実装は、LandBehaviourとWaterBehaviour(複合パターンの最上位層)と呼ばれる2つの抽象クラスです。これらのそれぞれには、サブクラスのコレクションがあります。LandBehaviourのみに焦点を当て、そのサブクラスはSnowBehaviour、StandardBehaviour、およびLandAssemblyを含む他のいくつかです。
LandBehaviourにコンポジットの上位層のコードを配置するというアイデアでした。次に、各具象サブクラスには、コンポジットの追加、削除、およびリスト部分の空の実装があり、LandAssemblyクラスには、さまざまな動作を実際に組み合わせるために必要なコードが含まれています。
これは、たとえば、車がStandardBehaviourとSnowBehaviourの両方を同時に持つことができるという結果を生成することを目的としています。
大量のコードを投稿するのではなく(そしてたくさんのコードがあります)、実装しようとしている基本構造についてのフィードバックを期待していました。現在、nullポインターの例外などのエラーがいくつか発生しており、それらを修正するために長い時間を費やすのではなく、プロジェクトのレイアウトが最初から正しいかどうかを把握したいと思いました。
編集:コードの追加-nullポインター例外を生成します
これは私の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コンストラクターの「新しい」部分が機能しなかったことも認識しています。動作ごとに空のコンストラクターを追加する必要がありました。
作成したコードに明白な問題が見られますが、それらを修正する方法がよくわかりません。