2016-04-18 10 views
1

以下は私のコードの分離です。間違ったアプローチまたは誤ったOOP設計?

インタラクティブインターフェイス。

public interface Interactable <E extends Interactable> { 

    List<Person> personsInteracting = new ArrayList<>(); 
    List<Person> personsWaiting  = new ArrayList<>(); 

    long INTERACTION_TIME = 5 * 60; 

    default int getNumberOfPeopleInteracting() { 
     return personsInteracting.size(); 
    } 

    default int getNumberOfPeopleWaiting() { 
     return personsWaiting.size(); 
    } 

    boolean isMultipleActionsAllowed(); 

    boolean isFurtherActionsAllowed(); 

    public abstract boolean tryOccupiedBy (final Person person, final Interactions interaction) 
     throws InteractionNotPossibleException; 

    E getObject(); 

    EnumSet<Interactions> getInteractions(); 
} 

InteractiveObjectの抽象クラス

public abstract class InteractiveObject implements Interactable { 

    protected final String  name; 
    protected  int   numberOfSimultaneousInteractions; 
    protected  Interactions currentInteraction; 

    public InteractiveObject (final String name) { 
     this.name = name; 
    } 

    @Override 
    public boolean isMultipleActionsAllowed() { 
     return numberOfSimultaneousInteractions > 1; 
    } 

    @Override 
    public boolean isFurtherActionsAllowed() { 
     return personsInteracting.isEmpty() || 
       (getNumberOfPeopleInteracting() > numberOfSimultaneousInteractions); 
    } 

    @Override 
    public boolean tryOccupiedBy (final Person person, final Interactions interaction) 
     throws InteractionNotPossibleException { 
     boolean isOccupied = false; 
     if (!isFurtherActionsAllowed()) { 
      throw new InteractionNotPossibleException(this + " is already in use by some other " + 
                 "person."); 
     } 
     personsInteracting.add(person); 
     currentInteraction = interaction; 
     return isOccupied; 
    } 

    @Override 
    public String toString() { 
     return name; 
    } 

    public int getNumberOfSimultaneousInteractions() { 
     return numberOfSimultaneousInteractions; 
    } 
} 

議長(子クラスの一つ)

public class Chair extends InteractiveObject { 

    private final EnumSet<Interactions> INTERACTIONS = EnumSet.copyOf(Arrays.asList(
     new Interactions[] {Interactions.DRAG, Interactions.SIT})); 

    public Chair (final String objectName) { 
     super(objectName); 
     super.numberOfSimultaneousInteractions = 1; 
    } 

    @Override 
    public Interactable getObject() { 
     return this; 
    } 

    @Override 
    public EnumSet<Interactions> getInteractions() { 
     return INTERACTIONS; 
    } 
} 

これは実行して問題を引き起こすコードです。この質問には次のようなものがあります。

 final InteractiveObject chair1 = new Chair("Chair1"); 
     final Person   person1 = new Person("Person1"); 
     final Room    room = new Room("Room1", 2, 2); 
     room.personEnters(person1); 
     room.putObject(chair1); 
     person1.tryOccupying(chair1); 

以上のコードは、正常に椅子オブジェクトを占有しています。さて、コードの

 final InteractiveObject chair2 = new Chair("Chair2"); 
     final Person   person2 = new Person("Person2"); 
     final Room    room2 = new Room("Room2", 2, 2); 
     room2.personEnters(person2); 
     room2.putObject(chair2); 
     person2.tryOccupying(chair2); 

この作品は私のコードは、1人はすでに誰もそれと対話されていないようchair2、と相互作用していると述べているのでperson2が占有することはできません。私の問題の

ソリューション:

私はInteractiveObjectpersonInteractingの私のリストを移動し、それぞれの子クラスにtryOccupiedBy機能、すべてが正常に動作します。

質問:

  1. 私は相互作用のすべての将来の実装がそれを持っていると信じているので、私はインタフェースInteractableでpersonsInteractingを置きます。開発者は自分自身を実装する必要はありません。 (しかし、おそらくこの考え方は間違っているように思われる)

  2. tryOccupiedByの機能に同じ実装がある場合、OOP全体の目的は何ですか?

  3. ここで、分離が間違っていることを知り、結果を得るためにピースを配置する場所を知っています。しかし、誰かが私が理解していないいくつかのOOPの概念について親切に指摘できますか?

答えて

2

defaultキーワードは、達成しようとしているようなことをするためにJava言語に追加されていません。インターフェースで定義されたデータは定数であることを意図しています - 修飾子 'public static'はインターフェース内の任意のフィールド定義に自動的に適用されます。インターフェイスにdefaultメソッドを作成する場合は、ステートレスであるか、まったく静的に使用可能な状態でのみ直接動作する必要があります。デフォルトのメソッドは、他のインタフェースメソッドを呼び出してインスタンスの状態を変更することができます。

personsInteractingフィールドをインターフェイスに配置すると、そのインターフェイスを実装するすべてのオブジェクトに同じインスタンスが共通化されたため、tryOccupyingメソッドは純粋にグローバルな状態で動作していました。

したがって、defaultメソッドをJava言語で使用する目的は、新しいメソッドを後方互換性のある方法でインターフェースに追加することをサポートすることです。それをコード再利用の一般的な形式として再利用するべきではありません。それは決して意図されたものではありません。

あなたはしかし、子クラスにtryOccupiedByを入れてを持っていなかったので、あなたはが重複したコードの負荷を持ってを持っていませんでした。あなたはまだインターフェイスのメソッドシグネチャを宣言することができます(これは一般にどのようなインタフェースが想定されているかです)。その後、抽象基本クラスに共通メソッドを実装します。データフィールドを基底クラスに置くと、インスタンスがフィールドになるため、オブジェクト間で共有されません。

public interface Interactable <E extends Interactable> { 
    ... 
    boolean tryOccupiedBy (final Person person, final Interactions interaction) 
     throws InteractionNotPossibleException; 
    ... 
} 

public abstract class InteractiveObject implements Interactable { 
    private final List<Person> personsInteracting = new ArrayList<>(); 
    private final List<Person> personsWaiting  = new ArrayList<>(); 
    ... 
    @Override 
    public final boolean tryOccupiedBy (final Person person, final Interactions interaction) 
     throws InteractionNotPossibleException { 
     boolean isOccupied = false; 
     if (!isFurtherActionsAllowed()) { 
      throw new InteractionNotPossibleException(this + " is already in use by some other " + 
                 "person."); 
     } 
     personsInteracting.add(person); 
     currentInteraction = interaction; 
     return isOccupied; 
    } 
    ... 
} 
+0

良い点は、回答が含まれています。 – sisyphus

関連する問題