2012-07-09 9 views
6

ठीक है, मान लीजिए कि मेरे पास कक्षा है, एक्स और एक्स कुछ ऐसा है जो अन्य वस्तुओं के साथ एक समग्र संबंध है। चलो बहाना एक्स एक फुटबॉल स्टेडियम है।क्या यह बुरा ओओ प्रोग्रामिंग है? विधियों के माध्यम से इसे नीचे

एक्स कक्षा दर्शकों से भरा है। हालांकि, किसी विशेष गतिविधि के लिए प्रत्येक दर्शक का व्यवहार अलग-अलग होता है। अगर कथन के बजाय, मैं चाहता हूं कि विभिन्न व्यवहार दर्शक वर्ग के भीतर हों, ताकि मैं गतिशील बाध्यकारी का उपयोग कर सकूं।

हालांकि, समस्या यह है कि दर्शकों का व्यवहार "सॉकर स्टेडियम" वर्ग को प्रभावित करता है। तो मैं सॉकर स्टेडियम कक्षा से "इस" को एक विधि के माध्यम से, स्पेक्ट्रेटर कक्षा में पास करने की सोच रहा था, ताकि दर्शक वर्ग सॉकर स्टेडियम कक्षा में कुछ कर सके?

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(); 
    } 
} 

मैं केवल यह करने के लिए इतना है कि मैं गतिशील बंधन का उपयोग करें और Specator.doSomething() में व्यवहार में परिवर्तन कर सकते हैं, ताकि मैं एक विशेषता SoccerStadium के लिए पारित रूप में SpectatorSuperClass के विभिन्न प्रकार के बहुत सारे है और उसके बाद अलग व्यवहार कर सकते हैं।

संपादित करें: क्या होगा यदि मैंने this पास करने के बजाय स्पेक्ट्रेटर कन्स्ट्रक्टर के माध्यम से स्पीकर के स्पीकर के संदर्भ को पारित किया?

+2

मेरा मानना ​​है कि शुद्ध तकनीक तंग युग्मन के कारण उस तकनीक पर क्रिंग करेगी, लेकिन ऐसा व्यापक रूप से उपयोग किया जाता है। एक "बेहतर" दृष्टिकोण एक इंटरफेस बनाने के लिए हो सकता है जो स्टेडियम लागू करता है जो परिभाषित करता है कि बाहरी इकाई क्या कर सकती है और स्टेडियम को अपने स्पेक्ट्रेटर वर्ग में उस इंटरफ़ेस प्रकार के रूप में स्वीकार करती है। – itsme86

+4

specator फुटबॉल स्टेडियम को कैसे प्रभावित करता है? ऐसा लगता है कि यहां सबसे अच्छे प्रकार के रिश्ते को निर्धारित करने में एक महत्वपूर्ण बात है। –

+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(); 
} 
} 

, आप तो, अपने "दर्शक" वर्गों के सभी अंदर अपने अन्य वर्ग है करने के लिए होता है, जो कर सकते थे: यह पूरी तरह से स्पष्ट तुम क्या करने की कोशिश कर रहे हैं क्या नहीं है, लेकिन कुछ इस तरह संभव है एक वास्तव में लंबी फ़ाइल के लिए नेतृत्व, और इस प्रकार, बदसूरत कोड।

हालांकि, मुझे लगता है कि आपको निश्चित रूप से दोनों चीजों को करने से बचना चाहिए, क्योंकि यह निश्चित रूप से आपके कोड को अत्यधिक जटिल बना देगा।

+0

हाय, दोनों चीजें मेरा प्रश्न और मेरा संपादन है? – user997112

+0

क्षमा करें, आपका अधिकार, यह बहुत स्पष्ट नहीं है।मैं कहने की कोशिश कर रहा था: आंतरिक वर्गों का उपयोग न करें और फिर आंतरिक वर्ग में बाहरी वर्ग का संदर्भ दें। मैंने इसे पहले देखा है, और मैं ऐसा नहीं सोच सकता कि आपको कभी ऐसा करने की आवश्यकता होगी। –

3

यह इतना बुरा नहीं है क्योंकि यह coupled है। this पॉइंटर्स के पास गुजरने के साथ स्वाभाविक रूप से गलत कुछ भी नहीं है, लेकिन यह बहुत गड़बड़ हो सकता है। हम वास्तव में अधिक जानकारी के बिना और अधिक नहीं कह सकते हैं।

+0

मैं थोड़े सूचक द्वारा एक विधि पारित करने के लिए कोशिश कर रहा हूँ मैं गतिशील स्पेक्टेटर इंटरफ़ेस है, जो स्टेडियम से पुकारा जाता है, स्टेडियम पर कार्रवाई करने के लिए के माध्यम से बाध्यकारी उपयोग कर रहा हूँ छोड़कर (के रूप में आप सी में होगा ++) .... मैं नहीं कर सकते लगता है किसी भी अन्य तरीके से ..... – user997112

+0

बस सोचा, क्या होगा अगर "इस" को पारित करने के बजाय, मैंने स्पेक्ट्रेटर कन्स्ट्रक्टर के माध्यम से स्टेडियम में स्पीकर के संदर्भ को पारित किया? – user997112

+0

@ user997112 क्या एक 'स्पेक्ट्रेटर' को अक्सर 'स्टेडियम' पर कार्य करने की आवश्यकता होती है? यदि एक 'स्पेक्ट्रेटर' एक 'स्टेडियम' से जुड़ा हुआ है, तो यह एक बेहतर समाधान होगा। – cklab

2

मुझे पैरामीटर के रूप में इसका उपयोग करने में कोई समस्या नहीं है। फिर भी, मुझे new Spectator() कॉल पसंद नहीं है जो आपके SoccerStadium कक्षा में हार्ड कोड किया गया था। मेरा मानना ​​है कि आपके पास createSpectator विधि वाला फ़ैक्टरी होना चाहिए जो एक पैरामीटर प्राप्त कर सकता है जो दर्शाता है कि आप किस प्रकार के दर्शक को बनाना चाहते हैं।

+0

के एक उदाहरण से जुड़ा हुआ है ईमानदार होने के लिए जो कुछ मैंने तुरंत खटखटाया था- मैं स्पेक्ट्रेटर को स्टेडियम में निर्माता के माध्यम से पास कर सकता था, या, मेरे संपादन की तरह, मैं उलटा कर सकता था? – user997112

+0

मेरी टिप्पणी के बारे में बिंदु यह है कि आपका कोड नया स्पेक्ट्रेटर() एक विशिष्ट प्रकार के स्पेक्ट्रेटर के साथ स्टेडियम को कसकर जोड़ता है। मैं सोच रहा था कि आप फैक्टरी पैटर्न का उपयोग कर सकते हैं। फिर भी, मुझे लगता है कि आपके पास प्रत्येक स्टेडियम में एक से अधिक दर्शक होने जा रहे हैं, इसलिए आप स्टेडियम में एक सूची (या एक अन्य कंटेनर) और एक ऐड विधि प्राप्त कर सकते हैं जो स्पेक्ट्रेटर इंटरफेस पैरामीटर के रूप में प्राप्त होगा। इसके बाद, स्टेडियम कुछ कह सकता है (यह)। – rlinden

2

मेरे लिए, इस तरह के दो-तरफा परिपत्र संबंध बुरी खबर है। क्या होगा अगर दर्शक थिएटर में जाना चाहते हैं?

मैं स्टेडियम को स्पेक्ट्रेटर प्रेषित घटनाओं के लिए ग्राहक बनाकर रिश्ते को रद्द कर दूंगा।

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); 
     } 
    } 
} 

... और इसलिए दर्शक अब कुछ भी दिलचस्पी रखता है, लेकिन इस बारे में एक बात पता करने की जरूरत नहीं है करने के लिए संवाद स्थापित करने का एक साधन है।

+0

मेरे ईडीआईटी प्रस्ताव के बारे में क्या? – user997112

+1

विभिन्न स्पेक्ट्रेटर 'कंटेनर' से संबंधित मेरा संपादन देखें। मैं चीजों का निर्माण करता हूं ताकि छोटे हिस्से अपने कंटेनरों पर निर्भर न हों। यह मुझे बहुत अच्छी तरह से सेवा करता है। – spender

+0

क्या मैं परेशानी हो सकता हूं और एक कोड उदाहरण मांग सकता हूं (अगर मेरा संपादन किया जा रहा है तो मेरा उपयोग कर रहे हैं)? – user997112

2

जैसा कि लोगों ने कहा है, बिल्कुल गलत कसकर युग्मन और आप क्या कर रहे हैं, बिल्कुल कुछ भी नहीं है। हालांकि, अगर आप थोड़ा सा decoupling चाहते हैं, क्लासिक विज़िटर पैटर्न का उपयोग करें।

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()); 
} 

यात्रा विधि हस्ताक्षर के रूप में अच्छी तरह से अगर आप की जरूरत है राज्य वस्तु किसी तरह स्वीकार करने के लिए बदला जा सकता है। अन्यथा आप स्पेक्ट्रेटर कक्षा पर प्रासंगिक तरीकों को परिभाषित कर सकते हैं, और आगंतुक को स्टेडियम को बदलने के लिए आवश्यक जानकारी एकत्र कर सकते हैं।

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

जैसा कि मैट ने कहा, आप जो वर्णन कर रहे हैं वह विज़िटर पैटर्न है। फिर भी, मुझे नहीं लगता कि यह आपका सबसे अच्छा विकल्प है (जैसा कि फल्मररी ने कहा था, उस तरह के डिज़ाइन को कसकर जोड़ना पड़ता है, और आप SoC, SRP, आदि तोड़कर, अपने व्यापार ऑब्जेक्ट में बहुत अधिक तर्क डालते हैं।)। तथ्य यह है कि किसी विशेष गतिविधि के लिए प्रत्येक दर्शक का व्यवहार अलग-अलग होता है, इसका मतलब यह नहीं है कि दर्शक को दर्शक वर्ग के माध्यम से शामिल किया जाना चाहिए (न ही पास)। उन IF बयानों से बचने के कई तरीके हैं। मेरा सुझाव है कि आप this link जैसे कुछ के साथ जाएं, जो कि बयान, विज़िटर पैटर्न या अन्य सभी विकल्पों की तुलना में कहीं अधिक शक्तिशाली है, और इसे किसी अन्य वर्ग में लागू करना वास्तव में आसान है, और उन सभी वस्तुओं को ओओपी सिद्धांतों (जो कि एक कारण के लिए हैं)।

संबंधित मुद्दे