⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pat4d.htm

📁 Design Pattern 设计模式
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<SCRIPT>
function setFocus() {	
	if ((navigator.appName != "Netscape") && (parseFloat(navigator.appVersion) == 2)) {
	return;
	} else {
	self.focus();
	}
}
</SCRIPT><HTML><HEAD>	<TITLE>Decorator</TITLE></HEAD><BODY	BGCOLOR	= #FFFFFF	TEXT = #000000
onLoad="setFocus()";><A NAME="top"></A><A NAME="Decorator"></A><A NAME="intent"></A><H2><A HREF="#alsoknownas"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Also Known As"></A> Intent</H2> <A NAME="auto1000"></A><P>Attach additional responsibilities to an object dynamically.Decorators provide a flexible alternative to subclassing for extendingfunctionality.</P><A NAME="alsoknownas"><A><H2><A HREF="#motivation"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Motivation"></A> Also Known As</H2> <A NAME="auto1001"></A><P>Wrapper</P><A NAME="motivation"></A><H2><A HREF="#applicability"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Applicability"></A> Motivation</H2> <A NAME="auto1002"></A><P>Sometimes we want to add responsibilities to individual objects, notto an entire class.  A graphical user interface toolkit, for example,should let you add properties like borders or behaviors like scrollingto any user interface component.</P><A NAME="auto1003"></A><P>One way to add responsibilities is with inheritance.  Inheriting aborder from another class puts a border around every subclassinstance.  This is inflexible, however, because the choice of borderis made statically. A client can't control how and when to decoratethe component with a border.</P><A NAME="dec-175"></A><P>A more flexible approach is to enclose the component in another objectthat adds the border.  The enclosing object is called a<STRONG>decorator</STRONG>.  The decorator conforms to the interface of thecomponent it decorates so that its presence is transparent to thecomponent's clients.  The decorator forwards requests to the componentand may perform additional actions (such as drawing a border) beforeor after forwarding.  Transparency lets you nest decoratorsrecursively, thereby allowing an unlimited number of addedresponsibilities.</P><P ALIGN=CENTER><IMG SRC="Pictures/decor066.gif"></P><A NAME="auto1004"></A><P>For example, suppose we have a TextView object that displays text in awindow.  TextView has no scroll bars by default, because we might notalways need them.  When we do, we can use a ScrollDecorator to addthem.  Suppose we also want to add a thick black border around theTextView.  We can use a BorderDecorator to add this as well.  Wesimply compose the decorators with the TextView to produce the desiredresult.</P><A NAME="auto1005"></A><P>The following object diagram shows how to compose a TextView objectwith BorderDecorator and ScrollDecorator objects to produce abordered, scrollable text view:</P><A NAME="scrolldecorator-176o"></A><A NAME="textview-176o"></A><P ALIGN=CENTER><IMG SRC="Pictures/decor065.gif"></P><A NAME="auto1006"></A><P>The ScrollDecorator and BorderDecorator classes are subclasses ofDecorator, an abstract class for visual components that decorate othervisual components.</P><A NAME="dec-176"></A><A NAME="scrolldecorator-176c"></A><A NAME="textview-176c"></A><P ALIGN=CENTER><IMG SRC="Pictures/decor067.gif"></P><A NAME="visual-comp"></A><P>VisualComponent is the abstract class for visual objects. Itdefines their drawing and event handling interface.  Note how theDecorator class simply forwards draw requests to its component,and how Decorator subclasses can extend this operation.</P><A NAME="auto1007"></A><P>Decorator subclasses are free to add operations for specificfunctionality.  For example, ScrollDecorator's ScrollTo operation letsother objects scroll the interface <EM>if</EM> they know there happens tobe a ScrollDecorator object in the interface.  The important aspect ofthis pattern is that it lets decorators appear anywhere aVisualComponent can.  That way clients generally can't tell thedifference between a decorated component and an undecorated one, andso they don't depend at all on the decoration.</P><A NAME="applicability"></A><H2><A HREF="#structure"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Structure"></A> Applicability</H2> <A NAME="auto1008"></A><P>Use Decorator</P><UL><A NAME="auto1009"></A><LI>to add responsibilities to individual objectsdynamically and transparently, that is, without affecting otherobjects.</LI><A NAME="auto1010"></A><P></P><A NAME="auto1011"></A><LI>for responsibilities that can be withdrawn.</LI><A NAME="auto1012"></A><P></P><A NAME="auto1013"></A><LI>when extension by subclassing is impractical.  Sometimes a largenumber of independent extensions are possible and would produce anexplosion of subclasses to support every combination.  Or a classdefinition may be hidden or otherwise unavailable for subclassing.</LI></UL><A NAME="structure"></A><H2><A HREF="#participants"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Participants"></A> Structure</H2> <P ALIGN=CENTER><IMG SRC="Pictures/decor064.gif"></P><A NAME="participants"></A><A NAME="participants"></A><H2><A HREF="#collaborations"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Collaborations"></A> Participants</H2><UL><A NAME="auto1014"></A><LI><B>Component</B> (VisualComponent)</LI><A NAME="auto1015"></A><P></P>    <UL>    <A NAME="auto1016"></A><LI>defines the interface for objects that can have    responsibilities added to them dynamically.</LI>    </UL><A NAME="auto1017"></A><P></P><A NAME="auto1018"></A><LI><B>ConcreteComponent</B> (TextView)</LI><A NAME="auto1019"></A><P></P>    <UL>    <A NAME="auto1020"></A><LI>defines an object to which additional responsibilities    can be attached.</LI>    </UL><A NAME="auto1021"></A><P></P><A NAME="dec-part"></A><LI><B>Decorator</B></LI><A NAME="auto1022"></A><P></P>    <UL>    <A NAME="auto1023"></A><LI>maintains a reference to a Component object and defines an interface    that conforms to Component's interface.</LI>    </UL><A NAME="auto1024"></A><P></P><A NAME="auto1025"></A><LI><B>ConcreteDecorator</B> (BorderDecorator, ScrollDecorator)</LI><A NAME="auto1026"></A><P></P>    <UL>    <A NAME="auto1027"></A><LI>adds responsibilities to the component.</LI>    </UL></UL><A NAME="collaborations"></A><H2><A HREF="#consequences"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Consequences"></A> Collaborations</H2><UL><A NAME="auto1028"></A><LI>Decorator forwards requests to its Component object.  It may optionallyperform additional operations before and after forwarding the request.</LI></UL><A NAME="consequences"></A><H2><A HREF="#implementation"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Implementation"></A> Consequences</H2> <A NAME="auto1029"></A><P>The Decorator pattern has at least two key benefits and twoliabilities:</P><OL><A NAME="auto1030"></A><LI><EM>More flexibility than static inheritance.</EM>The Decorator pattern provides a more flexible way to addresponsibilities to objects than can be had with static (multiple)inheritance.  With decorators, responsibilities can be added andremoved at run-time simply by attaching and detaching them. Incontrast, inheritance requires creating a new class for eachadditional responsibility (e.g., BorderedScrollableTextView,BorderedTextView).  This gives rise to many classes and increases thecomplexity of a system.  Furthermore, providing different Decoratorclasses for a specific Component class lets you mix and matchresponsibilities.<A NAME="auto1031"></A><P>Decorators also make it easy to add a property twice. For example, togive a TextView a double border, simply attach twoBorderDecorators.  Inheriting from a Border class twice is error-proneat best.</P></LI><A NAME="auto1032"></A><P></P><A NAME="auto1033"></A><LI><EM>Avoids feature-laden classes high up in the hierarchy.</EM>Decorator offers a pay-as-you-go approach to adding responsibilities.Instead of trying to support all foreseeable features in a complex,customizable class, you can define a simple class and add functionalityincrementally with Decorator objects.  Functionality can be composed fromsimple pieces.  As a result, an application needn't pay for featuresit doesn't use.  It's also easy to define new kinds of Decoratorsindependently from the classes of objects they extend, even forunforeseen extensions.  Extending a complex class tends to exposedetails unrelated to the responsibilities you're adding.</LI><A NAME="auto1034"></A><P></P><A NAME="auto1035"></A><LI><EM>A decorator and its component aren't identical.</EM>A decorator acts as a transparent enclosure.  But from an objectidentity point of view, a decorated component is not identical to thecomponent itself.  Hence you shouldn't rely on object identity whenyou use decorators.</LI><A NAME="auto1036"></A><P></P><A NAME="auto1037"></A><LI><EM>Lots of little objects.</EM>A design that uses Decorator often results in systems composed oflots of little objects that all look alike.  The objects differ onlyin the way they are interconnected, not in their class or in the valueof their variables.  Although these systems are easy to customizeby those who understand them, they can be hard to learn and debug.</LI></OL><A NAME="implementation"></A><H2><A HREF="#samplecode"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Sample Code"></A> Implementation</H2> <A NAME="auto1038"></A><P>Several issues should be considered when applying the Decorator pattern:</P><OL><A NAME="auto1039"></A><LI><EM>Interface conformance.</EM>A decorator object's interface must conform to the interface of thecomponent it decorates.  ConcreteDecorator classes must thereforeinherit from a common class (at least in C++).</LI><A NAME="auto1040"></A><P></P><A NAME="auto1041"></A><LI><EM>Omitting the abstract Decorator class.</EM>There's no need to define an abstract Decorator class when you onlyneed to add one responsibility.  That's often the case when you'redealing with an existing class hierarchy rather than designing a newone.  In that case, you can merge Decorator's responsibility forforwarding requests to the component into the ConcreteDecorator.</LI><A NAME="auto1042"></A><P></P><A NAME="lightvsheavy"></A><LI><EM>Keeping Component classes lightweight.</EM>To ensure a conforming interface, components and decorators mustdescend from a common Component class. It's important to keep thiscommon class lightweight; that is, it should focus on defining aninterface, not on storing data.  The definition of the datarepresentation should be deferred to subclasses; otherwise thecomplexity of the Component class might make the decorators tooheavyweight to use in quantity.  Putting a lot of functionality intoComponent also increases the probability that concrete subclasses willpay for features they don't need.</LI><A NAME="auto1043"></A><P></P><A NAME="dec-strat"></A><A NAME="strat-vs-decor"></A><LI><EM>Changing the skin of an object versus changing its guts.</EM>We can think of a decorator as a skin over an object that changes itsbehavior. An alternative is to change the object's guts.  The <A HREF="pat5ifs.htm" TARGET="_mainDisplayFrame">Strategy (315)</A> pattern is a good example of a pattern forchanging the guts.<A NAME="auto1044"></A><P>Strategies are a better choice in situations where the Component classis intrinsically heavyweight, thereby making the Decorator pattern toocostly to apply.  In the Strategy pattern, the component forwards someof its behavior to a separate strategy object.  The Strategy patternlets us alter or extend the component's functionality by replacing thestrategy object.</P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -