7

タグ付けされたクラスと大きな if-else ブロックまたは switch ステートメントの使用を避け、代わりにクラス階層でポリモーフィズムを使用したいと考えています。これはより良い方法だと思います。

たとえば、実行されるメソッドの選択が Actor タイプのオブジェクトの 1 つのフィールドのみに依存する以下のようなものです。

switch(actor.getTagField())
{
    case 1: actor.act1(); break;
    case 2: actor.act2(); break;
    [...]
}

になるだろう

actor.act();

act メソッドは Actor のサブクラスでオーバーライドされます。

ただし、どのサブクラスをインスタンス化するかを実行時に決定する最も明白な方法は、元のものと非常によく似ています。

Actor newActor(int type)
{
    switch(type)
    {
        case 1: return new Actor1();
        case 2: return new Actor2();
        [...]
    }
}

そのため、実際には何も得られていないようです。ロジックは移動されたばかりです。

これを行うためのより良い方法は何ですか? 私が思いつく唯一の方法は、Actor の各サブクラスのファクトリ クラスを実装することですが、これは、このような単純な問題ではかなり面倒に思えます。

私はこれを考えすぎていますか?他の場所でほとんど同じことをするだけでは、元の変更を行う意味がないように思えます。

4

3 に答える 3

4

問題は、工場が必要かどうかです。ファクトリは、関連するインスタンスの動作ではなく、インスタンスの作成を管理することを目的としています。

それ以外の場合は、基本的な継承を見ているだけです。何かのようなもの..

class Actor{
  public void act(){
    System.out.println("I act..");
  }
}

class StuntActor extends Actor {
  public void act(){
    System.out.println("I do fancy stunts..");
  }
}

class VoiceActor extends Actor {
  public void act(){
    System.out.println("I make funny noises..");
  }
}

使用するには、必要なタイプのアクターを直接インスタンス化するだけです。

Actor fred = new Actor();
Actor tom = new VoiceActor();
Actor sally = new StuntActor();

fred.act();
tom.act();
sally.act();

出力:

I act..
I make funny noises..
I do fancy stunts..

編集:

アクターの作成を一元化する必要がある場合、別名ファクトリに対して、ある種のスイッチング ロジックから逃れることはできません。その場合、通常、読みやすさのために列挙を使用します。

public class Actor{
  public enum Type{ REGULAR, VOICE, STUNT }

  public static Actor Create(Actor.Type type){
    switch(type) {
      case VOICE:
        return new VoiceActor();
      case STUNT:
        return new StuntActor();
      case REGULAR:
      default:
        return new Actor();
    }
  }

  public void act(){
    System.out.println("I act..");
  }
}

使用法:

Actor some_actor = Actor.Create(Actor.Type.VOICE);
some_actor.act();

出力:

I make funny noises..
于 2012-04-28T22:52:45.317 に答える
3

Switchステートメントは純粋な悪ではありません。あなたがより良いデザインで排除しようとしているのは本当に重複です。多くの場合、同じswitchステートメントがコード内の異なる(遠くの)場所に表示されます。必ずしも同じことを行う必要はありませんが、同じデータをオンにします。ポリモーフィズムを導入することにより、これらのスイッチを同じオブジェクトの異なるメソッドとしてまとめます。

これは2つのことを行います。まず、工場内の複数のスイッチを1つのスイッチに減らし、同様のデータに依存する可能性のある分散ロジックをまとめます。そのデータは、オブジェクトのメンバー変数に変わります。

また、ファクトリの内部でswitchステートメントが表示されるとは限らないことにも注意してください。HashMap起動時にクラスパスをスキャンして、インターフェイスを実装するタイプのを構築できるかもしれません。たとえば、SMTPのようなソケットプロトコルの実装を考えてみましょう。HeloCommand、などの名前MailFromCommandのオブジェクトを作成し、socketコマンドをクラス名と照合することで、メッセージを処理するための適切なオブジェクトを見つけることができます。

于 2012-04-29T00:49:33.683 に答える
2

Abstract factoryパターンでできると思います...

これは例です:

abstract class Computer {
    public abstract Parts getRAM();
    public abstract Parts getProcessor();
    public abstract Parts getMonitor();
}

class Parts {
    public String specification;
    public Parts(String specification) {
        this.specification = specification;
    }
    public String getSpecification() {
        return specification;
    }
}

拡張する2つのクラスがありますComputer

class PC extends Computer {
    public Parts getRAM() {
        return new Parts("512 MB");
    }
    public Parts getProcessor() {
        return new Parts("Celeron");
    }
    public Parts getMonitor() {
        return new Parts("15 inches");
    }
}

class Workstation extends Computer {
    public Parts getRAM() {
        return new Parts("1 GB");
    }
    public Parts getProcessor() {
        return new Parts("Intel P 3");
    }
    public Parts getMonitor() {
        return new Parts("19 inches");
    }
}

そして最後に、

public class ComputerType {
    private Computer comp;
    public static void main(String[] args) {
        ComputerType type = new ComputerType();
        Computer computer = type.getComputer("Workstation");
        System.out.println("Monitor: "+computer.getMonitor().getSpecification());
        System.out.println("RAM: "+computer.getRAM().getSpecification());
        System.out.println("Processor: "+computer.getProcessor().getSpecification());
    }    

    public Computer getComputer(String computerType) {
        if (computerType.equals("PC"))
            comp = new PC();
        else if(computerType.equals("Workstation"))
            comp = new Workstation();
        return comp;
    }    
}
于 2012-04-28T22:42:09.770 に答える