2016-08-07 8 views
1

さて、私は基本的に何をしたいのかという例で私の質問を始めたいと思います。静的メソッドを実行するために必要なデザインパターン

IDogというインターフェースを実装して、実装にいくつかのメソッドを持たせたいと思っています。また、すべてのDogクラスに基本属性とメソッドを与えるスーパークラスAbstractDog implements IDogが必要です。次にサブクラスをPoodle extends AbstractDogのようにしたいと思います。ここで私の問題はstaticメソッドです - 基本的にAbstractDogの各サブクラスに異なるstaticメソッドを持たせたいですが、このメソッドをIDogから実行できるようにしたいと考えています。

だから私のナイーブ(間違った)の実装は次のようになります。私が言ったように

public interface IDog { 

    String getName(); // every dog instance should be able to call name 
    static String getDescription(); // every dog class should be able to get its description 

} 

public abstract class AbstractDog implements IDog { 

    private String name; // every dog instance will have this 

    public AbstractDog(String name) { 
     this.name = name; 
    } 

    @Override 
    public String getName() { 
     return this.name; // every dog instance can call this 
    } 

} 

public class Poodle extends AbstractDog { 

    private static String description = "It's a poodle!"; // all Poodles have the same description 

    public Poodle(String name) { 
     super(name); 
    } 

    @Override // from IDog 
    public static String getDescription() { 
     return description; 
    } 

} 

さて、これは正しくないAbstractDogクラスはgetDescription()IDogは、そのメソッドの実装が必要static abstract方法が必要になるため、それを上書きすることはできません。

私の問題にマッチするデザインパターンがあるかどうかを知りたいと思っています。(別の!)静的メソッドを実装するためにクラスのセットを強制します(中間のスーパークラスを持つことができます)。

一つの可能​​性は、私が発見したが、それは、有益な、あるいは十分でありenum DogTypeの使用となり、その後、ちょうどDogType属性でclass Dogを持つかどうかはわからない:

public enum DogType { 

    Poodle("This is a poodle."), Havanese("This is a Havanese.)"; 

    private String description; 

    private DogType(String description) { 
     this.description = description; 
    } 

    public String getDescription() { 
     return this.description; 
    } 
} 

public class Dog { 

    private String name; 
    private DogType dogType; 

    public Dog(String name, DogType dogType) { 
     this.name = name; 
     this.dogType = dogType; 
    } 

    public String getName() { 
     return this.name; 
    } 

    public String getDescription { 
     return this.dogType.getDescription(); 
    } 
} 

しかし、この「回避策」は当初のアイデアよりも能力を失っています。インスタンスメソッドvoid prance()のような唯一の犬のクラスには、今やPoodleにアクセスできるような追加機能はありません。

同様の質問に関する多くのトピックはファクトリパターンを参照していますが、必ずしも構築方法が必要なわけではないため、私の問題にどのように適合するかはわかりません。そして、犬種族の数が増えるにつれて、私のコードが非常に混乱するようになると思います。あるいは、私の場合、Factoryをどのように正しく使うべきかを知りませんでした。

+0

'public String getDescription(){ return"プードルです! "; } '??? – fabian

答えて

2

これはコードの匂いである可能性が高いです。

静的メソッドが常にクラスのすべてのオブジェクトに対して同じものを返す場合は、それを通常のgetメソッドにするだけです。

@Override \\ from IDog 
public String getDescription() { 
    return "This is a poodle"; 
} 

静的変数を変更できる場合は、このクラス全体の状態を保持する新しいオブジェクトを作成し、コンストラクタの各クラスに与えます。

ex。

// StringState is a new class that holds a string and has a set and get method 
StringState desc = new StringState("original description"); 
IDog dog1 = new Poodle(desc); 
IDog dog2 = new Poodle(desc); 
// prints original description 
System.out.Println(dog1.getDescription()); 
System.out.Println(dog2.getDescription()); 

desc.set("New description"); 
// prints new description, since both objects share the same 
// StringState,changing it here changes it in all of them. 
System.out.Println(dog1.getDescription()); 
System.out.Println(dog2.getDescription()); 
+0

この実装では 'Poodle.getDescription()'を呼び出すことができません。記述を得る能力は 'プードル'のインスタンスから独立しているべきです。 (そして、私の例は悪いと思ったので、 "Poodlesは一種の犬です。Blah blah。") – Paul

3

インターフェイスは強制的な動作です。クラスはプロパティを指定するために使用されます。静的メソッドは非表示になります。それらはサブクラスによってオーバーライドされません。したがって、サブクラスに静的メソッドがあり、オブジェクト参照がスーパータイプクラスである場合、スーパークラスからの静的メソッドが呼び出されます。これはクラス隠蔽です。静的メソッドで発生します。(!異なる)の静的メソッドを実装する(または中間 スーパークラスを持たなければならない可能性が)クラスのセットを強制 :デザイン私の問題と一致するパターンがあるかどう

私は、知りたいです。

申し訳ありません。静的メソッドと継承は手を通しません。

私は今だけ プードルにアクセスできる必要が インスタンスメソッドのボイド跳ねる(のような唯一の犬のクラスへの追加機能)をすることはできません。

Prancableのインタフェースをvoid prance()で導入することができます。

public interface Prancable{ 
     void prance(); 
} 
public class Poodle extends Dog implements Prancable{ 
     @Override 
     public void prance(){ 
      System.out.println("My Poodle can prance."); 
     } 
} 

このようにして、異なる犬種別に行動を追加する方法に進むことができます。

+0

最終的には、私のような 'enum DogType'それを定義?次に、(継承された)属性 'DogType dogType'を持つ' Poodle'クラスと、 'super(name、DogType.Poodle)'を呼び出すコンストラクタ 'Poodle(String name)しかし、それほど冗長ではないのですか? – Paul

+0

'Dog'スーパータイプから' enum DogType'を継承しても問題ありません。 'DogType'を使って、' DogFactory'からさまざまなタイプのDogを生成することができます。 –

+0

これ以上説明できますか? – Paul

関連する問題