2012-07-09 7 views
6

私はクラスがあると仮定します.XとXは他のオブジェクトとの集約関係を持つものです。 Xがサッカースタジアムであると思わせる。これは不正なプログラミングですか?これをメソッドに渡す

Xはクラス観客でいっぱいです。しかし、特定の活動に対する各観客の行動は異なる。 IF文の代わりに、違う振る舞いを観客クラス内に入れて、動的バインディングを使うことができます。

しかし、問題は、観客の行動が「サッカースタジアム」クラスに影響することです。だから私は、サッカースタジアムのクラスからメソッドを介してSpectatorクラスに "this"を渡して、観客クラスがサッカースタジアムのクラスに何かできるようにすることを考えていましたか?

public class SoccerStadium{ 
    SpecatorInterface s = new Spectator(); 

    public void SpectatorBehaviour(){ 
     s.doSomething(this); 
    } 

    public void doSomethingthingBySpecator(){ 
    } 
} 

public class Spectator implements SpecatorInterface{ 
    public void doSomething(SoccerStadium s){ 
     s.doSomethingthingBySpecator(); 
    } 
} 

私は私がSoccerStadiumに渡された属性としてSpectatorSuperClassの異なる種類がたくさんあるし、別の行動を持つことができるように、私は動的バインディングを使用してSpecator.doSomething()で動作を変更できるように、これを実行したいです。

EDIT:thisを渡すのではなく、スペクテーターコンストラクターを通じてスタジアムの参照を渡した場合はどうなりますか?

+2

私は純粋なカップリングのために純粋主義者がこのテクニックを嫌うと信じていますが、広く使われているようです。 「より良い」アプローチは、スタジアムが実装するインターフェイスを作成し、外部エンティティがそれを行うことができるものを定義し、スタジアムを観客クラスのインターフェイスタイプとして受け入れることです。 – itsme86

+4

スペイサーはサッカースタジアムにどのくらいの影響を与えますか?ここでは、最良のタイプの関係を決定することが重要なポイントです。 –

+0

@Esteban、非常に単純なロジック、値に属性を設定する。重いものはありません – user997112

答えて

1

あなたの実装はまったく問題ありません。私はそのようなことを以前から見てきました。はい、スタジアムのリファレンスを保持することができます。スペクトレータのコンストラクタを通過させることで、必要なときにリファレンスを送信するよりもクリーンである可能性があります。

しかし、私はあまり好きではありません。私は内部クラスを好む。それはあなたが何をしようとして完全には明らかではないが、このようなものが可能です:

public class Outer { 

private int someVariable=0; 

public void someMethod(){ 
    ExtendsInner ei = new ExtendsInner(); 
    ei.innerMethod(); 
    System.out.println(someVariable); 
} 

private void anotherMethod(){ 
    someVariable++; 
} 

public abstract class Inner { 
    public abstract void innerMethod(); 
} 

public class ExtendsInner extends Inner{ 
    public void innerMethod(){ 
     anotherMethod(); 
     someVariable++; 
    } 
} 

public static void main(String[] args){ 
    Outer o = new Outer(); 
    o.someMethod(); 
} 
} 

残念ながら、あなたは、可能性がある内部のあなたの「観客」クラスのすべてあなたの他のクラスを、持っている必要があります本当に長いファイルが1つあり、ひどいコードになります。

しかし、私は間違いなくあなたのコードを過度に複雑にしてしまうので、両方のことを避けるべきだと思います。

+0

こんにちは、両方のことが私の質問と私の編集ですか? – user997112

+0

申し訳ありませんが、あなたの権利は、それほど明確ではありません。私は言うことをしようとしていた:内部クラスを使用していないし、内部クラスの外部クラスへの参照を配置しないでください。私は前にこれが行われていることを見てきました。あなたがこれを行う必要があるとは思えません。 –

3

これは厳密にはcoupledであるため、これはあまり「悪いプログラミング」ではありません。何も本質的にthisポインターを渡すことに間違っているが、非常に非常に迅速に混乱することができます。私たちはもっと多くの情報がなくても、もっと言い表すことはできない。

+0

スタジアムで動作するSpectatorインターフェイスを介してダイナミックバインディングを使用している点を除いて、私はちょっとポインタ(C++のように)でメソッドを渡そうとしています....私は考える..... – user997112

+0

"this"を渡す代わりに、私はスタジアムのリファレンスをSpectatorコンストラクタを通してSpecatorに渡したとしたらどうでしょうか? – user997112

+0

@ user997112「観衆」はしばしば異なる「スタジアム」で行動する必要がありますか? 「観客」が単一の「スタジアム」に縛られている場合、それはより良い解決策になるでしょう。 – cklab

2

これをパラメータとして使用すると問題はありません。それにもかかわらず、あなたのSoccerStadiumクラスでハードコーディングされたnew Spectator()コールが好きではありません。私はあなたが作成しようとしている観客のタイプを示すパラメータを受け取ることができるcreateSpectatorメソッドを持つ工場を持っている必要がありますと信じています。

+0

正直言って、私はすぐにノックアップしました - 私は観客をコンストラクター経由でスタジアムに渡すことができました。私はその逆をすることができますか? – user997112

+0

私のコメントについてのポイントは、新しいSpectator()が特定の種類のSpectatorとスタジアムを緊密に結びつけていることです。私はあなたがFactoryパターンを使うことができると考えていました。それにもかかわらず、私はあなたがおそらく各スタジアムに複数の観客を持っていると思うので、スタジアムのリスト(または別のコンテナ)とSpectatorInterfaceをパラメータとして受け取るaddメソッドを持つことができます。その後、スタジアムはdoSomething(this)を呼び出すことができます。 – rlinden

2

私にとっては、このような双方向循環関係は悪いニュースです。観客が代わりに劇場に行きたい場合はどうすればいいですか?

私はスタジアムをSpectatorディスパッチイベントの加入者にすることで、関係を切り離しています。

public class SoccerStadium 
{ 
    ISpectator s = new Spectator(); 
    public SoccerStadium() 
    { 
     s.DidSomething+=DoSomethingthingBySpecator; 
    } 
    public void SpectatorBehaviour() 
    { 
     s.DoSomething(); 
    } 
    public void DoSomethingthingBySpecator(object sender,EventArgs e) 
    { 
     Console.WriteLine("spectator did something"); 
    } 
} 
public interface ISpectator 
{ 
    event EventHandler DidSomething; 
    void DoSomething(); 
} 
public class Spectator:ISpectator 
{ 
    public event EventHandler DidSomething; 
    public void DoSomething() 
    { 
     var ev=DidSomething; 
     if(ev!=null) 
     { 
      ev(this,EventArgs.Empty); 
     } 
    } 
} 

...そういうわけで、Spectatorは興味のあるものと通信する手段を持っていますが、それについてのことを知る必要はありません。

+0

私のEDIT提案はどうですか? – user997112

+1

別のSpectator 'containers'に関する私の編集を参照してください。小さな部品が容器に頼らないように物を作る傾向があります。それは私を非常にうまく扱う。 – spender

+0

私は面倒で、コード例を尋ねることができますか? – user997112

2

人々が言っ​​ているように、タイトなタイトな結合と間違ったことは絶対にありません。しかし、少しデカップリングしたい場合は、古典的なビジターパターンを使用してください。

public interface SpectatorVisitor { 
    ... 
    void visit(Spectator spectator); 
} 

public class Spectator { 
    ... 
    public void accept(SpectatorVisitor visitor) { 
     visitor.visit(this); 
    } 
} 

public class Stadium { 

    ... 
    spectator.accept(new StadiumSpectatorVisitor()); 
} 

訪問メソッドのシグネチャは、必要に応じて何らかの状態オブジェクトを受け入れるように変更することができます。それ以外の場合は、Spectatorクラスで関連するメソッドを定義し、訪問者がスタジアムを変更するために必要な情報を収集できるようにすることができます。例えば

public class Spectator { 
    private Team supports; 

    public Team getSupports() { 
     return supports; 
    } 

    public void accept(SpectatorVisitor visitor) { 
     visitor.visit(this); 
    } 
} 

public class SupportedTeamVisitor { 
    private Map<Team, AtomicLong> supportCount = new HashMap<Team, AtomicLong>(); 

    public void visit(Spectator spectator) { 
    Team supports = spectator.getSupports(); 
    if (! supportCount.contains(supports)) { 
     supportCount.put(team, new AtomicLong(0)); 
    } 
    supports.get(team).incrementAndGet(); 
    } 

    public Map<Team, AtomicLong> getSupportCount() { 
    return supportCount; 
    } 
} 


public class Stadium { 

    public long getSupportCount(Team team) { 
    SupportTeamVisitor visitor = new SupportedTeamVisitor(); 
    for (Spectator spectator : spectators) { 
     spectator.accept(visitor); 
    } 
    AtomicLong count = visitor.getSupportCount().get(team); 
    return (count == null) ? 0 : count.get(); 
    } 
} 

は意味をなさない?

1

Mattが言ったように、あなたが記述しているのはビジターパターンです。それにもかかわらず、私はそれがあなたの最善の選択肢だとは思わない(Falmarriが言ったように、その種のデザインはしっかりと結合して、ビジネスオブジェクトに多くのロジックを置くことになり、SoCSRPなど)。 特定のアクティビティに対する各観客の振る舞いが異なるという事実は、そのロジックが観客クラスに含まれるべきではないということを意味するものではありません。これらのIF文を避ける方法はたくさんあります。私は、this linkのように、if文、訪問者のパターン、または他のすべての選択肢よりはるかに強力であることを示唆しています。そして、他のクラスで実装するのは本当に簡単です。理由がありますか?)

関連する問題