2012-02-12 11 views
18

मैं सोलिड और अन्य डिज़ाइन सिद्धांतों के बारे में पढ़ रहा था। मैंने सोचा था कि आईएसपी "एक इंटरफेस के लिए कार्यक्रम, एक कार्यान्वयन नहीं" जैसा ही था। लेकिन ऐसा लगता है कि ये अलग-अलग सिद्धांत हैं?इंटरफ़ेस पृथक्करण सिद्धांत- एक इंटरफ़ेस पर प्रोग्राम

क्या कोई अंतर है?

उत्तर

26

आईएसपी प्रत्येक इंटरफेस के विचार पर केंद्रित है जो एक अलग और एकजुट व्यवहार का प्रतिनिधित्व करता है।

यही है, वस्तुओं के प्रत्येक लॉजिकल समूह को एक ऑब्जेक्ट करना चाहिए जो एक विशिष्ट इंटरफ़ेस को मैप करेगा। एक कक्षा कई चीजें करना चाहती है, लेकिन प्रत्येक चीज उस व्यवहार का प्रतिनिधित्व करने वाले विशिष्ट इंटरफेस को मैप करेगी। विचार यह है कि प्रत्येक इंटरफ़ेस बहुत केंद्रित है।

+1

लघु और बिंदु – Gordon

+1

वाह .. धन्यवाद! एक और 5 मिनट के लिए स्वीकार नहीं कर सकते :) – hangar18

+3

+1। क्लासिक "गंध" जो आपको बताती है कि आप इस सिद्धांत का पालन नहीं कर रहे हैं वह एक ग्राहक है जो एक इंटरफ़ेस (निर्भर करता है) एक इंटरफ़ेस है जहां क्लाइंट केवल इंटरफ़ेस के तरीकों का सबसेट कहता है। एक विस्तृत स्पष्टीकरण के लिए समय निकालने के लिए – TrueWill

32

रॉबर्ट मार्टिन ने अपनी पुस्तक "यूएमएल फॉर जावा प्रोग्रामर" में इंटरफेस अलगाव सिद्धांत (आईएसपी) का बहुत अच्छा स्पष्टीकरण दिया है। उस पर आधारित, मुझे नहीं लगता कि आईएसपी एक तार्किक, सुसंगत समूह पर "केंद्रित" होने के बारे में है। क्योंकि, यह बिना कहने के चला जाता है; या, कम से कम इसे बिना कहने के जाना चाहिए। प्रत्येक वर्ग, इंटरफेस या अमूर्त वर्ग को इस तरह से डिजाइन किया जाना चाहिए।

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

पर सीधे की है कि इंटरफेस पर निर्भर करते हैं, बजाय होगा,

class A { 
    method1() 
    method2() 
    // more methods 
    method10() 
} 
class B { 
    A a = new A() 

} 

बन जाएगा

interface C { 
     method1() 
     method2() 
} 



class A implements C{ 
     method1() 
     method2() 
     // more methods 
     method10() 
    } 
    class B { 
     C c = new A() 

} 

यह बी को इससे ज्यादा जानने से रोकता है।

+0

+1! – hangar18

+0

उत्कृष्ट जवाब! –

+1

मुझे लगता है कि @Pete Stensønes स्पष्टीकरण मेरे द्वारा किए गए कार्यों की तुलना में अधिक सामान्य और सटीक है। मैं लोगों को उनकी परिभाषा पर अधिक ध्यान देने का सुझाव देता हूं। मेरा, हालांकि जरूरी नहीं है, इसके उपयोग के मामले में अवधारणा को समझाता है, इसका सामान्य बिंदु गुम है। –

1

उपरोक्त दोनों उत्तरों के साथ सहमत हैं। बस TrueWill के कोड गंध का एक उदाहरण देने के लिए ऊपर, आप अपने आप को ऐसा करने नहीं मिल चाहिए:

@Override 
public void foo() { 
    //Not used: just needed to implement interface 
} 
+0

जावा एपीआई कक्षाओं के साथ तुलना करें जो विशेष रूप से संग्रह में एक NotImplementedException फेंक देते हैं। मॉडरेशन में प्रयुक्त यह इंटरफ़ेस में आंशिक रूप से उपयोग की जाने वाली विधियों के लिए उपयोगी हो सकता है, हालांकि उदाहरण के लिए, MutableMap के साथ मानचित्र का विस्तार करना वैकल्पिक विकल्प हो सकता था। – hexafraction

0

यहाँ इस सिद्धांत का एक वास्तविक दुनिया उदाहरण है (PHP में)

समस्या विवरण:

मैं विभिन्न प्रकार की सामग्री चाहता हूं कि उनके साथ टिप्पणियां/चर्चा हो। यह सामग्री फ़ोरम विषय से, किसी समाचार आलेख में, उपयोगकर्ता की प्रोफ़ाइल पर, वार्तालाप-शैली निजी संदेश में कुछ भी हो सकती है।

वास्तुकला

हम एक फिर से प्रयोग करने योग्य DiscussionManager वर्ग जो किसी दिए गए सामग्री संस्था के लिए एक Discussion देता चाहते है। हालांकि, उपरोक्त चार उदाहरण (और कई और) सभी अवधारणात्मक रूप से अलग हैं। अगर हम उन्हें उपयोग करने के लिए DiscussionManager चाहते हैं, तो सभी चार + को एक आम इंटरफ़ेस होना चाहिए जो वे सभी साझा करते हैं। DiscussionManager के लिए उनका उपयोग करने के लिए कोई अन्य तरीका नहीं है जब तक कि आप नग्न होने के लिए अपने तर्क नहीं चाहते (उदा। कोई प्रकार की जांच नहीं)।

समाधान: इन तरीकों के साथ Discussable इंटरफ़ेस:

  • attachDiscussion($topic_id)
  • detachDiscussion()
  • getDiscussionID()

फिर DiscussionManager इस प्रकार दिखाई देंगे:

class DiscussionManager 
{ 
    public function addDiscussionToContent(Discussable $Content) 
    { 
     $Discussion = $this->DiscussionFactory->make(...some data...); 
     $Discussion->save() // Or $this->DiscussionRepository->save($Discussion); 
     $Content->attachDiscussion($Discussion->getID()); // Maybe saves itself, or you can save through a repository 
    } 

    public function deleteDiscussion(Discussable $Content) 
    { 
     $id = $Content->getDiscussionID(); 
     $Content->detatchDiscussion(); 
     $this->DiscussionRepository->delete($id); 
    } 

    public function closeDiscussion($discussion_id) { ... } 
} 

इस तरह, DiscussionManager यह का उपयोग करता है विभिन्न सामग्री प्रकार के असंबंधित से कोई भी व्यवहार के बारे में परवाह नहीं है। यह केवल उन व्यवहारों की परवाह करता है जिनकी आवश्यकता है, भले ही वे व्यवहार किस प्रकार से जुड़े हों। इसलिए Discussable इंटरफ़ेस के लिए प्रत्येक सामग्री प्रकार को आप चर्चा करना चाहते हैं, तो आप इंटरफ़ेस पृथक्करण सिद्धांत का उपयोग कर रहे हैं।

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

यह उदाहरण भी PHP में लक्षण के उपयोग के लिए एक अच्छे उम्मीदवार, क्या इसके लायक है के लिए हो सकता है।

7

मान लें आप कई तरीके के साथ एक वसा इंटरफ़ेस लागू किया जाना है।

किसी भी वर्ग, को लागू करता है कि वसा इंटरफ़ेस इन सभी तरीकों के लिए कार्यान्वयन प्रदान करने के लिए है। कुछ विधियां उस ठोस वर्ग पर लागू नहीं हो सकती हैं। लेकिन फिर भी इसे इंटरफेस अलगाव सिद्धांत की अनुपस्थिति में कार्यान्वयन प्रदान करना है।

के इंटरफ़ेस अलगाव की अभाव में उदाहरण कोड पर एक नजर है।

interface Shape{ 
    public int getLength(); 
    public int getWidth(); 
    public int getRadius(); 
    public double getArea(); 
} 

class Rectangle implements Shape{ 
    int length; 
    int width; 
    public Rectangle(int length, int width){ 
     this.length = length; 
     this.width = width; 
    } 
    public int getLength(){ 
     return length; 
    } 
    public int getWidth(){ 
     return width; 
    } 
    public int getRadius(){ 
     // Not applicable 
     return 0; 
    } 
    public double getArea(){ 
     return width * length; 
    } 
} 
class Square implements Shape{ 
    int length; 

    public Square(int length){ 
     this.length = length; 
    } 
    public int getLength(){ 
     return length; 
    } 
    public int getWidth(){ 
     // Not applicable 
     return 0; 
    } 
    public int getRadius(){ 
     // Not applicable 
     return 0; 
    } 
    public double getArea(){ 
     return length * length; 
    } 
} 

class Circle implements Shape{ 
    int radius; 
    public Circle(int radius){ 
     this.radius = radius; 
    } 
    public int getLength(){ 
     // Not applicable 
     return 0; 
    } 
    public int getWidth(){ 
     // Not applicable 
     return 0; 
    } 
    public int getRadius(){ 
     return radius; 
    } 
    public double getArea(){ 
     return 3.14* radius * radius; 
    } 
} 

public class InterfaceNoSeggration{ 
    public static void main(String args[]){ 
     Rectangle r = new Rectangle(10,20); 
     Square s = new Square(15); 
     Circle c = new Circle(2); 
     System.out.println("Rectangle area:"+r.getArea()); 
     System.out.println("Square area:"+s.getArea()); 
     System.out.println("Circle area:"+c.getArea()); 

    } 
} 

उत्पादन:

java InterfaceNoSeggration 
Rectangle area:200.0 
Square area:225.0 
Circle area:12.56 

नोट्स:

  1. Shape एक सामान्य प्रयोजन वसा इंटरफेस है, जो सभी Shape कार्यान्वयन Rectangle, Circle और Square तरह के लिए आवश्यक तरीकों में शामिल है। लेकिन केवल कुछ तरीकों संबंधित आकार में की जरूरत है childs

    Rectangle : getLength(), getWidth(), getArea() 
    Square : getLength() and getArea() 
    Circle : getRadius() and getArea() 
    
  2. अलगाव के अभाव में, सभी आकृतियाँ पूरे वसा इंटरफेस को लागू किया है: आकार।

हम इस प्रकार अगर हम कोड बदलने इंटरफ़ेस अलगाव सिद्धांत के साथ ही उत्पादन प्राप्त कर सकते हैं।

interface Length{ 
    public int getLength(); 
} 
interface Width{ 
    public int getWidth(); 
} 
interface Radius{ 
    public int getRadius(); 
} 
interface Area { 
    public double getArea(); 
} 


class Rectangle implements Length,Width,Area{ 
    int length; 
    int width; 
    public Rectangle(int length, int width){ 
     this.length = length; 
     this.width = width; 
    } 
    public int getLength(){ 
     return length; 
    } 
    public int getWidth(){ 
     return width; 
    } 
    public int getRadius(){ 
     // Not applicable 
     return 0; 
    } 
    public double getArea(){ 
     return width * length; 
    } 
} 
class Square implements Length,Area{ 
    int length; 

    public Square(int length){ 
     this.length = length; 
    } 
    public int getLength(){ 
     return length; 
    } 
    public int getWidth(){ 
     // Not applicable 
     return 0; 
    } 
    public int getRadius(){ 
     // Not applicable 
     return 0; 
    } 
    public double getArea(){ 
     return length * length; 
    } 
} 

class Circle implements Radius,Area{ 
    int radius; 
    public Circle(int radius){ 
     this.radius = radius; 
    } 
    public int getLength(){ 
     // Not applicable 
     return 0; 
    } 
    public int getWidth(){ 
     // Not applicable 
     return 0; 
    } 
    public int getRadius(){ 
     return radius; 
    } 
    public double getArea(){ 
     return 3.14* radius * radius; 
    } 
} 

public class InterfaceSeggration{ 
    public static void main(String args[]){ 
     Rectangle r = new Rectangle(10,20); 
     Square s = new Square(15); 
     Circle c = new Circle(2); 
     System.out.println("Rectangle area:"+r.getArea()); 
     System.out.println("Square area:"+s.getArea()); 
     System.out.println("Circle area:"+c.getArea()); 

    } 
} 

नोट्स:

Rectangle, Square और Circle की तरह अब अलग-अलग आकार केवल आवश्यक इंटरफेस को लागू किया है और अन-इस्तेमाल किया तरीकों से छुटकारा मिला।

+0

मैंने इस पर -1 वोट दिया लेकिन असल में यह एक गलती थी, मुझे यह जवाब पसंद है: डी –

+0

मैं टिप्पणियों के साथ नीचे मतदान के बारे में हैरान हूं। यदि सिस्टम अनुमति देता है तो आप इसे सही कर सकते हैं। अन्यथा आपको 24 घंटों के बाद आना होगा :) –

+0

मेरे पास यह संदेश है: "" आपने आखिरी बार 3 घंटे पहले इस उत्तर पर मतदान किया था। –

0
  1. IWorker इंटरफ़ेस:

    public interface IWorker { 
        public void work(); 
        public void eat(); 
    
    } 
    
  2. डेवलपर कक्षा:

    public class Developer implements IWorker { 
    
        @Override 
        public void work() { 
          // TODO Auto-generated method stub 
          System.out.println("Developer working"); 
    
        } 
    
        @Override 
        public void eat() { 
          // TODO Auto-generated method stub 
          System.out.println("developer eating"); 
    
        } 
    
    } 
    
  3. रोबोट कक्षा:

    public class Robot implements IWorker { 
    
        @Override 
        public void work() { 
          // TODO Auto-generated method stub 
          System.out.println("robot is working"); 
    
        } 
    
        @Override 
        public void eat() { 
          // TODO Auto-generated method stub 
          throw new UnsupportedOperationException("cannot eat"); 
    
        } 
    
    } 
    

एक और पूर्ण उदाहरण के लिए here पर जाएं।

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