2016-10-27 6 views
6

में सजावटी डिजाइन पैटर्न को समझना मैंने अभी सजावट डिजाइन पैटर्न सीखना शुरू किया, दुर्भाग्यवश मुझे सजावट पैटर्न को बेहतर ढंग से समझने के लिए विभिन्न सुधारों से गुजरना पड़ा जिससे मुझे बहुत भ्रम पैदा हुआ। हां, जहां तक ​​मेरी समझ चिंता का विषय है, मेरा मानना ​​है कि यह एक डेकोरेटर पैटर्नसी #

interface IComponent 
    { 
     void Operation(); 
    } 
    class Component : IComponent 
    { 
     public void Operation() 
     { 
      Console.WriteLine("I am walking "); 
     } 
    } 
    class DecoratorA : IComponent 
    { 
     IComponent component; 
     public DecoratorA(IComponent c) 
     { 
      component = c; 
     } 
     public void Operation() 
     { 
      component.Operation(); 
      Console.WriteLine("in the rain"); 
     } 
    } 
    class DecoratorB : IComponent 
    { 
     IComponent component; 
     public DecoratorB(IComponent c) 
     { 
      component = c; 
     } 
     public void Operation() 
     { 
      component.Operation(); 
      Console.WriteLine("with an umbrella"); 
     } 
    } 
    class Client 
    { 
     static void Main() 
     { 
      IComponent component = new Component(); 
      component.Operation(); 

      DecoratorA decoratorA = new DecoratorA(new Component()); 
      component.Operation(); 

      DecoratorB decoratorB = new DecoratorB(new Component()); 
      component.Operation(); 

      Console.Read(); 
     } 
    } 

है, लेकिन नीचे कोड भी डेकोरेटर पैटर्न हो सकता है?

class Photo 
{ 
    public void Draw() 
    { 
     Console.WriteLine("draw a photo"); 
    } 
} 
class BorderedPhoto : Photo 
{ 
    public void drawBorder() 
    { 
     Console.WriteLine("draw a border photo"); 
    } 
} 
class FramePhoto : BorderedPhoto 
{ 
    public void frame() 
    { 
     Console.WriteLine("frame the photo"); 
    } 
} 
class Client 
{ 
    static void Main() 
    { 
     Photo p = new Photo(); 
     p.Draw(); 

     BorderedPhoto b = new BorderedPhoto(); 
     b.Draw(); 
     b.drawBorder(); 

     FramePhoto f = new FramePhoto(); 
     f.Draw(); 
     f.drawBorder(); 
     f.frame(); 
    } 
} 

मेरी समझ

मेरे द्वारा दिए गए दूसरे उदाहरण से, हम तीनों विधियों कॉल कर सकते हैं, लेकिन पहले उदाहरण से मैं पैदा करके तीनों विधियों तक पहुँच प्राप्त करने सकेंगे एक वस्तु

+0

1 - सजावट, 2 - नहीं। मेरे बिंदु से, सजावटी को सजाए गए ऑब्जेक्ट को लपेटना चाहिए :) – tym32167

+1

सजावटी मानकों का विस्तार करने का अनुमान है, ठीक है !!! तो दूसरा दूसरा सजावट पैटर्न क्यों नहीं है? क्या आप मुझे समझने में मदद कर सकते हैं? –

+2

@LijinJohn मैं यह कहूंगा क्योंकि एक सजावटी * एक मौजूदा उदाहरण * सजाता है। अगर मेरे पास पहले से ही 'फोटो' का उदाहरण है, तो मैं इसे 'बोर्डर्ड फोटो' का उपयोग करके आसानी से सजाने नहीं कर सकता, मुझे 'बोर्डर्ड फोटो' का एक उदाहरण बनाना होगा और फिर मेरे मूल 'फोटो' इंस्टेंस से गुणों को कॉपी करना होगा। वह सजा नहीं है। – Kyle

उत्तर

7

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

उदाहरण के लिए, आपके पास ऑब्जेक्ट और इंटरफ़ेस है, जैसे Repository : IRepository

public interface IRepository 
{ 
    void SaveStuff(); 
} 

public class Repository : IRepository 
{ 
    public void SaveStuff() 
    { 
     // save stuff 
    } 
} 

और ग्राहक है, जो शायद द्वारा नहीं आप

class RepoClient 
{ 
    public void DoSomethig(IRepository repo) 
    { 
     //... 
     repo.SaveStuff(); 
    } 
} 

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

public class RepositoryLogDecorator : IRepository 
{ 
    public IRepository _inner; 

    public RepositoryLogDecorator(IRepository inner) 
    { 
     _inner = inner; 
    } 

    public void SaveStuff() 
    { 
     // log enter to method 
     try 
     { 
      _inner.SaveStuff(); 
     } 
     catch(Exception ex) 
     { 
      // log exception 
     }  
     // log exit to method 
    } 
} 

की तरह तो, इससे पहले कि आप के रूप में

var client = new RepoClient(); 
client.DoSomethig(new Repository()); 

ग्राहक इस्तेमाल कर सकते हैं, लेकिन अब आप उपयोग कर सकते हैं

var client = new RepoClient(); 
client.DoSomethig(new RepositoryLogDecorator(new Repository())); 

ध्यान दें, कि यह बहुत आसान उदाहरण है। असली परियोजनाओं में, जहां ऑब्जेक्ट डीआई कंटेनर के साथ प्राथमिक बनाया गया था, आप कुछ कॉन्फ़िगरेशन को बदलकर सजावटी का उपयोग करने में सक्षम हैं।

तो, सजावटी के लिए क्या उपयोग किया जाता है: ऑब्जेक्ट या क्लाइंट को बदले बिना ऑब्जेक्ट की कार्यक्षमता बढ़ाने के लिए।

सजावट का एक और लाभ: आपके सजावटी Repository कार्यान्वयन पर निर्भर नहीं हैं। केवल इंटरफ़ेस IRepository से निर्भर करता है। इसका लाभ क्यों है? यदि somewhen आप तय करेगा आप ही कार्यान्वयन

public class MyAwesomeRepository : IRepository 
{ 
    public void SaveStuff() 
    { 
     // save stuff, but AWESOME! 
    } 
} 
आप स्वचालित रूप से

डेकोरेटर के साथ इस को सजाने के लिए सक्षम लिखने के लिए है, जो पहले से ही मौजूद

var client = new RepoClient(); 
client.DoSomethig(new RepositoryLogDecorator(new MyAwesomeRepository())); 

असली सॉफ्टवेयर से उदाहरण देखना चाहते हैं? (जैसे नमूना, कोड बदसूरत है, मुझे पता है) =>go here

कूल! इसे प्यार करना! : डी

+0

महोदय, आपकी मदद के लिए आपको बहुत धन्यवाद :) –

0

दूसरा उदाहरण सजावट पैटर्न नहीं है, क्योंकि सजावटी पैटर्न के लिए एक आवश्यक घटक यह है कि वस्तु अपनी तरह से स्वीकार करती है और संभवतः इसे बढ़ाती है। पहले उदाहरण में इस बात का

एक उदाहरणों

public DecoratorA(IComponent c) { component = c; }

है इसके अलावा, डेकोरेटर पैटर्न के लक्ष्य को "एक" वस्तु है, तो बनाने के विभिन्न फिल्टर या सज्जाकार के माध्यम से पारित करके यह सजाने के लिए है। इसलिए लाइन

DecoratorA decoratorA = new DecoratorA(new Component());

होना चाहिए

DecoratorA decoratorA = new DecoratorA(component);

2

डेकोरेटर पैटर्न आपको लगता है कि के अन्य उदाहरण को प्रभावित किए बिना किसी दिए गए प्रकार के व्यक्ति वस्तु के लिए एक विशिष्ट व्यवहार जोड़ने की अनुमति देता इसी प्रकार का।

आपके दूसरे उदाहरण में, जो सामान्य विरासत है, सभी कक्षा के उदाहरण संशोधित व्यवहार का उत्तराधिकारी हैं।

1

प्रति GOF page डेकोरेटर desing पैटर्न:

एक वस्तु को गतिशील करने के लिए अतिरिक्त जिम्मेदारी देते हैं। सजावटी कार्यक्षमता विस्तार के लिए उपclassing के लिए एक लचीला विकल्प प्रदान करते हैं।

अपने दूसरे उदाहरण में आप कक्षा के व्यवहार को बढ़ाने के लिए विरासत का उपयोग कर रहे हैं, मेरा मानना ​​है कि यह तकनीकी रूप से सजावटी डिजाइन पैटर्न नहीं है।

2

यह PatternCraft series on Youtube है जो स्टारक्राफ्ट के साथ डिज़ाइन पैटर्न को बताता है, आपको check the video about Decorators here होना चाहिए।

लेखक के ऊपर दिए गए वीडियो में Marine और WeaponUpgrade के साथ एक उदाहरण दिया गया है।

खेल में आप होगा एक Marine और फिर आप अपने हथियार उन्नयन कर सकते हैं:

marine = new WeaponUpgrade(marine); 

ध्यान दें कि आप अभी भी वहाँ एक समुद्री है, यह एक नई इकाई नहीं है, यह चीजों के साथ एक ही इकाई है जो इसके गुणों को संशोधित करता है।

public class MarineWeaponUpgrade : IMarine 
{ 
    private IMarine marine; 

    public MarineWeaponUpgrade(IMarine marine) 
    { 
     this.marine = marine; 
    } 

    public int Damage 
    { 
     get { return this.marine.Damage + 1; } // here 
     set { this.marine.Damage = value; } 
    } 
} 

आप करना है कि एक वर्ग है कि आपके इकाई के रूप में एक ही इंटरफ़ेस लागू करता है और मूल्यों को संशोधित करने के लिए अपने इकाई गुण का उपयोग बनाने के द्वारा।

एक Kata on CodeWars है जो आपको समुद्री के लिए हथियार और आर्मर सजावटी को पूरा करने के लिए चुनौती देता है।

+0

आपके यूट्यूब लिंक के लिए धन्यवाद, वीडियो सहायक थे :) –