state
ロジックは、柔軟性がないことを既に示したとおりです。たとえば、一部のオブジェクトに対して異なる順序で操作を実行する必要がある場合 (3->1->2)、問題はさらに複雑になる可能性があります。
動作は主にSomeObject
型に依存するため、「クリーンな」アプローチの 1 つは、各オブジェクトを一連の構成可能なコマンド (コマンド パターン + コンポジット/デコレータ) に変換することだと思います。
/* Declare an interface for executing an operation */
public interface Command
{
public void execute();
public Command setNext();
public Boolean hasNext();
}
/* Abstract class providing compose-ability and chaining behavior for its children.
*/
public abstract class BaseCommand implements Command
{
private Command next;
public Boolean hasNext()
{
return next != null;
}
public Command setNext(Command nextC)
{
next = nextC;
return nextC;
}
public void execute(){
executeImpl();
if(hasNext()) next.execute();
}
public abstract void executeImpl();
}
これで、特定の処理に対応する一連のコマンドを定義できます (それぞれが状態メソッドの特定の「行」/ステップに直接マップされます)。
public class Step1Command extends BaseCommand
{
// If we need access to the SomeObject instance we can define a dependecy on it
// ex. through a constructor
//The necessary processing goes here
public void executeImpl(){
doStep1();
}
}
最後に、オブジェクトを一連のコマンドに変換する必要があります。これは、ファクトリ クラスを介して実現できます。
public class CommandFactory
{
//The necessary processing goes here
public Command create(SomeObjectA typeA){
Command firstCommand = new Step1Command(typeA);
Command secondCommand = new Step2Command(typeA);
//....
Command lastCommand = new StepXCommand(typeA);
//We can easily switch the order of processing for a particular object
fistCommand.setNext(secondCommand)
//...
.setNext(lastCommand);
return firstCommand;
}
}
あなたのコードは今どのように見えますか?
CommandFactory cFactory = new CommandFactory();
void state(SomeObject o) {
Command command = cFactory.create(o);
command.execute();
}
それで、付加価値は何ですか(これはやり過ぎのように見えるかもしれません)?
state
オブジェクトの種類に応じた処理は、メソッドから離れています。メソッドのオーバーロード + 継承により、if/else をバイパスできるようになります。
必要な処理 () の順序を簡単に入れ替えることができるため、ロジックが柔軟になります。
新しい SomeObject 実装処理を追加しても、既存のコードは変更されません (保守性 + 拡張性)