decorator pattern मौजूदा कक्षाओं में मौजूदा वर्गों को बदलने के बिना कार्यक्षमता जोड़ने के लिए एक डिज़ाइन पैटर्न है। इसके अलावा, एक सजावटी वर्ग खुद को किसी अन्य वर्ग के चारों ओर लपेटता है, और आमतौर पर सजाए गए वर्ग के समान इंटरफेस का खुलासा करता है।
बुनियादी उदाहरण:
interface Renderable
{
public function render();
}
class HelloWorld
implements Renderable
{
public function render()
{
return 'Hello world!';
}
}
class BoldDecorator
implements Renderable
{
protected $_decoratee;
public function __construct(Renderable $decoratee)
{
$this->_decoratee = $decoratee;
}
public function render()
{
return '<b>' . $this->_decoratee->render() . '</b>';
}
}
// wrapping (decorating) HelloWorld in a BoldDecorator
$decorator = new BoldDecorator(new HelloWorld());
echo $decorator->render();
// will output
<b>Hello world!</b>
अब, आप को लगता है कि क्योंकि Zend_Form_Decorator_*
कक्षाएं सज्जाकार हैं, और एक render
विधि है, यह स्वचालित रूप से render
विधि सजाया वर्ग के 'उत्पादन होगा हमेशा मतलब है परीक्षा हो सकती है सजावटी द्वारा अतिरिक्त सामग्री के साथ लपेटा जाना चाहिए।
class DivDecorator
implements Renderable
{
const PREPEND = 'prepend';
const APPEND = 'append';
const WRAP = 'wrap';
protected $_placement;
protected $_decoratee;
public function __construct(Renderable $decoratee, $placement = self::WRAP)
{
$this->_decoratee = $decoratee;
$this->_placement = $placement;
}
public function render()
{
$content = $this->_decoratee->render();
switch($this->_placement)
{
case self::PREPEND:
$content = '<div></div>' . $content;
break;
case self::APPEND:
$content = $content . '<div></div>';
break;
case self::WRAP:
default:
$content = '<div>' . $content . '</div>';
}
return $content;
}
}
// wrapping (decorating) HelloWorld in a BoldDecorator and a DivDecorator (with DivDecorator::APPEND)
$decorator = new DivDecorator(new BoldDecorator(new HelloWorld()), DivDecorator::APPEND);
echo $decorator->render();
// will output
<b>Hello world!</b><div></div>
इस में है: लेकिन इसके बाद के संस्करण हमारी बुनियादी उदाहरण के निरीक्षण पर, हम आसानी से यह अनिवार्य रूप से, के रूप में इस अतिरिक्त (यद्यपि काफी बेकार) उदाहरण के रूप में रेखांकित पाठ्यक्रम के सभी पर मामला हो की जरूरत नहीं है देख सकते हैं तथ्य यह है कि Zend_Form_Decorator_*
सजावटी कितने काम करते हैं, अगर उनके लिए यह प्लेसमेंट कार्यक्षमता हो।
सजावट करने वालों के लिए जहां यह समझ में आता है, उदाहरण के लिए, आप setOption('placement', 'append')
के साथ प्लेसमेंट को नियंत्रित कर सकते हैं, या विकल्पों के लिए 'placement' => 'append'
विकल्प को पास करके।
Zend_Form_Decorator_PrepareElements
के लिए, उदाहरण के लिए, इस नियुक्ति के विकल्प बेकार है और वजह, नजरअंदाज कर दिया के रूप में यह तैयार प्रपत्र तत्व एक ViewScript
डेकोरेटर द्वारा प्रयोग की जाने, यह सज्जाकार कि सजाया तत्व की प्रदान की गई सामग्री स्पर्श नहीं करता है में से एक बना ।
व्यक्तिगत सज्जाकार के डिफ़ॉल्ट कार्यक्षमता के आधार पर, या तो सजाया वर्ग की सामग्री, लिपटे संलग्न, prepended है, त्याग या कुछ पूरी तरह से अलग सजाया वर्ग के लिए किया जाता है, सीधे सामग्री के लिए कुछ जोड़े बिना, अगले सजावट करने के लिए सामग्री के साथ गुजरने से पहले। इस सरल उदाहरण पर विचार करें:
class ErrorClassDecorator
implements Renderable
{
protected $_decoratee;
public function __construct(Renderable $decoratee)
{
$this->_decoratee = $decoratee;
}
public function render()
{
// imagine the following two fictional methods
if($this->_decoratee->hasErrors())
{
$this->_decoratee->setAttribute('class', 'errors');
}
// we didn't touch the rendered content, we just set the css class to 'errors' above
return $this->_decoratee->render();
}
}
// wrapping (decorating) HelloWorld in a BoldDecorator and an ErrorClassDecorator
$decorator = new ErrorClassDecorator(new BoldDecorator(new HelloWorld()));
echo $decorator->render();
// might output something like
<b class="errors">Hello world!</b>
अब, जब आप एक Zend_Form_Element_*
तत्व के लिए सज्जाकार निर्धारित करते हैं, वे लिपटे हो जाएगा, और फलस्वरूप, जिसमें वे जोड़ रहे हैं क्रम में, मार डाला।तो, अपने उदाहरण को देखते हुए:
$decorate = array(
array('ViewHelper'),
array('Description'),
array('Errors', array('class'=>'error')),
array('Label', array('tag'=>'div', 'separator'=>' ')),
array('HtmlTag', array('tag' => 'li', 'class'=>'element')),
);
... मूल रूप से क्या होता है निम्नलिखित (वास्तविक वर्ग के नाम संक्षिप्तता के लिए छोटा कर दिया) है:
$decorator = new HtmlTag(new Label(new Errors(new Description(new ViewHelper()))));
echo $decorator->render();
तो, अपने उदाहरण उत्पादन की जांच पर, हम होना चाहिए व्यक्तिगत सजावट के डिफ़ॉल्ट प्लेसमेंट व्यवहार को दूर करने में सक्षम:
// ViewHelper->render()
<input type="text" name="title" id="title" value="">
// Description->render()
<input type="text" name="title" id="title" value="">
<p class="hint">No --- way</p> // placement: append
// Errors->render()
<input type="text" name="title" id="title" value="">
<p class="hint">No --- way</p>
<ul class="error"> // placement: append
<li>Value is required and cant be empty</li>
</ul>
// Label->render()
<label for="title" class="required">Title</label> // placement: prepend
<input type="text" name="title" id="title" value="">
<p class="hint">No --- way</p>
<ul class="error">
<li>Value is required and cant be empty</li>
</ul>
// HtmlTag->render()
<li class="element"> // placement: wrap
<label for="title" class="required">Title</label>
<input type="text" name="title" id="title" value="">
<p class="hint">No --- way</p>
<ul class="error">
<li>Value is required and cant be empty</li>
</ul>
</li>
और आप क्या जानते हैं; यह वास्तव में सभी संबंधित सज्जाकारों की डिफ़ॉल्ट नियुक्ति है।
लेकिन अब कठिन हिस्सा आता है, आपको जो परिणाम दिख रहा है उसे पाने के लिए हमें क्या करने की ज़रूरत है? आदेश label
और input
हम बस ऐसा नहीं कर सकते लपेटो करने के लिए:
$decorate = array(
array('ViewHelper'),
array('Description'),
array('Errors', array('class'=>'error')),
array('Label', array('tag'=>'div', 'separator'=>' ')),
array('HtmlTag', array('tag' => 'div')), // default placement: wrap
array('HtmlTag', array('tag' => 'li', 'class'=>'element')),
);
इस एक div के साथ सभी पूर्ववर्ती सामग्री (
ViewHelper
,
Description
,
Errors
और
Label
), सही लपेट के रूप में
...? यहां तक कि नहीं ... जोड़ा गया सजावटी अगले स्थान पर प्रतिस्थापित किया जाएगा, क्योंकि सजावटकर्ताओं को एक ही श्रेणी के होने पर निम्नलिखित सजावटकर्ता द्वारा प्रतिस्थापित किया जाता है।
$decorate = array(
array('ViewHelper'),
array('Description'),
array('Errors', array('class'=>'error')),
array('Label', array('tag'=>'div', 'separator'=>' ')),
array(array('divWrapper' => 'HtmlTag'), array('tag' => 'div')), // we'll call it divWrapper
array('HtmlTag', array('tag' => 'li', 'class'=>'element')),
);
अब, हम अभी भी समस्या यह है कि divWrapper
सभी पूर्ववर्ती सामग्री (ViewHelper
, Description
, Errors
और Label
) लपेट जाएगा के साथ सामना कर रहे हैं: जगह में आप यह एक अद्वितीय कुंजी देने के लिए करना होगा। तो हमें यहां रचनात्मक होने की जरूरत है। हम जो चाहते हैं उसे हासिल करने के कई तरीके हैं। मैं एक उदाहरण दे देंगे, कि शायद सबसे आसान है:
$decorate = array(
array('ViewHelper'),
array('Label', array('tag'=>'div', 'separator'=>' ')), // default placement: prepend
array(array('divWrapper' => 'HtmlTag'), array('tag' => 'div')), // default placement: wrap
array('Description'), // default placement: append
array('Errors', array('class'=>'error')), // default placement: append
array('HtmlTag', array('tag' => 'li', 'class'=>'element')), // default placement: wrap
);
Zend_Form
सज्जाकार मैं पढ़ Zend फ्रेमवर्क नेतृत्व डेवलपर मैथ्यू Weier O'Phinney के article about Zend Form Decorators
वाह, यह कुछ पूरा जवाब है! अच्छा है ! –
ओह वाह, मेरे पास उस जवाब में एक आह क्षण था, धन्यवाद और स्वीकार किया गया: डी –
पी.एस. यह सबसे आश्चर्यजनक उत्तर था कि कभी भी –