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

📄 pat4b.htm

📁 Design Pattern 设计模式
💻 HTM
📖 第 1 页 / 共 2 页
字号:
    Handle&amp; Handle::operator= (const Handle&amp; other)  {        other._body->Ref();        _body->Unref();            if (_body->RefCount() == 0) {            delete _body;        }        _body = other._body;            return *this;    }</PRE></LI><A NAME="auto1054"></A><P></P><A NAME="auto1055"></A><LI><EM>Using multiple inheritance.</EM> You can use multipleinheritance in C++ to combine an interface with its implementation [<A HREF="bibfs.htm#martin" TARGET="_mainDisplayFrame">Mar91</A>]. For example, a class can inheritpublicly from Abstraction and privately from a ConcreteImplementor.But because this approach relies on static inheritance, it bindsan implementation permanently to its interface. Therefore you can'timplement a true Bridge with multiple inheritance&#151;at leastnot in C++.</LI></OL><A NAME="samplecode"><A><H2><A HREF="#knownuses"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Known Uses"></A> Sample Code</H2> <A NAME="auto1056"></A><P>The following C++ code implements the Window/WindowImp example from theMotivation section. The <CODE>Window</CODE> class defines the window abstractionfor client applications:</P><A NAME="auto1057"></A><PRE>    class Window {    public:        Window(View* contents);            // requests handled by window        virtual void DrawContents();            virtual void Open();        virtual void Close();        virtual void Iconify();        virtual void Deiconify();            // requests forwarded to implementation        virtual void SetOrigin(const Point&amp; at);        virtual void SetExtent(const Point&amp; extent);        virtual void Raise();        virtual void Lower();            virtual void DrawLine(const Point&amp;, const Point&amp;);        virtual void DrawRect(const Point&amp;, const Point&amp;);        virtual void DrawPolygon(const Point[], int n);        virtual void DrawText(const char*, const Point&amp;);        protected:        WindowImp* GetWindowImp();        View* GetView();        private:        WindowImp* _imp;        View* _contents; // the window's contents    };</PRE><A NAME="windowimp2"></A><A NAME="xwindowimp2"></A><P><CODE>Window</CODE> maintains a reference to a <CODE>WindowImp</CODE>, theabstract class that declares an interface to the underlying windowingsystem.</P><A NAME="auto1058"></A><PRE>    class WindowImp {    public:        virtual void ImpTop() = 0;        virtual void ImpBottom() = 0;        virtual void ImpSetExtent(const Point&amp;) = 0;        virtual void ImpSetOrigin(const Point&amp;) = 0;            virtual void DeviceRect(Coord, Coord, Coord, Coord) = 0;        virtual void DeviceText(const char*, Coord, Coord) = 0;        virtual void DeviceBitmap(const char*, Coord, Coord) = 0;        // lots more functions for drawing on windows...    protected:        WindowImp();    };</PRE><A NAME="auto1059"></A><P>Subclasses of <CODE>Window</CODE> define the different kinds ofwindows the application might use, such as application windows,icons, transient windows for dialogs, floating palettes of tools,and so on.</P><A NAME="appwin"></A><P>For example, <CODE>ApplicationWindow</CODE> will implement<CODE>DrawContents</CODE> to draw the  <CODE>View</CODE> instanceit stores:</P><A NAME="auto1060"></A><PRE>    class ApplicationWindow : public Window {    public:        // ...        virtual void DrawContents();    };        void ApplicationWindow::DrawContents () {        GetView()->DrawOn(this);    }</PRE><A NAME="auto1062"></A><P><CODE>IconWindow</CODE> stores the name of abitmap for the icon it displays...</P><A NAME="auto1063"></A><PRE>    class IconWindow : public Window {    public:        // ...        virtual void DrawContents();    private:        const char* _bitmapName;    };</PRE><A NAME="auto1064"></A><P>...and it implements <CODE>DrawContents</CODE> to draw the bitmapon the window:</P><A NAME="auto1065"></A><PRE>    void IconWindow::DrawContents() {        WindowImp* imp = GetWindowImp();        if (imp != 0) {            imp->DeviceBitmap(_bitmapName, 0.0, 0.0);        }    }</PRE><A NAME="auto1066"></A><P>Many other variations of <CODE>Window</CODE> are possible.  A<CODE>TransientWindow</CODE> may need to communicate with the window thatcreated it during the dialog; hence it keeps a reference to thatwindow.  A <CODE>PaletteWindow</CODE> always floats above other windows.An <CODE>IconDockWindow</CODE> holds<CODE>IconWindow</CODE>s and arranges them neatly.</P><A NAME="auto1067"></A><P><CODE>Window</CODE> operations are defined in terms of the<CODE>WindowImp</CODE> interface.  For example,<CODE>DrawRect</CODE> extracts four coordinates from its two <CODE>Point</CODE>parameters before calling the<CODE>WindowImp</CODE> operation that draws the rectangle in the window:</P><A NAME="auto1068"></A><PRE>    void Window::DrawRect (const Point&amp; p1, const Point&amp; p2) {        WindowImp* imp = GetWindowImp();        imp->DeviceRect(p1.X(), p1.Y(), p2.X(), p2.Y());    }</PRE><A NAME="xwindowsys2"></A><P>Concrete subclasses of <CODE>WindowImp</CODE> support different windowsystems.  The <CODE>XWindowImp</CODE> subclass supports the X WindowSystem:</P><A NAME="auto1069"></A><PRE>    class XWindowImp : public WindowImp {    public:        XWindowImp();            virtual void DeviceRect(Coord, Coord, Coord, Coord);        // remainder of public interface...    private:        // lots of X window system-specific state, including:        Display* _dpy;        Drawable _winid;  // window id        GC _gc;           // window graphic context    };</PRE><A NAME="pmwindowimp"></A><A NAME="present-manage2"></A><P>For Presentation Manager (PM), we define a <CODE>PMWindowImp</CODE>class:</P><A NAME="auto1070"></A><PRE>    class PMWindowImp : public WindowImp {    public:        PMWindowImp();        virtual void DeviceRect(Coord, Coord, Coord, Coord);            // remainder of public interface...    private:        // lots of PM window system-specific state, including:        HPS _hps;    };</PRE><A NAME="auto1071"></A><P>These subclasses implement <CODE>WindowImp</CODE> operations in terms ofwindow system primitives. For example,<CODE>DeviceRect</CODE> is implemented  for X as follows:</P><A NAME="auto1072"></A><PRE>    void XWindowImp::DeviceRect (        Coord x0, Coord y0, Coord x1, Coord y1    ) {        int x = round(min(x0, x1));        int y = round(min(y0, y1));        int w = round(abs(x0 - x1));        int h = round(abs(y0 - y1));        XDrawRectangle(_dpy, _winid, _gc, x, y, w, h);    }</PRE><A NAME="auto1073"></A><P>The PM implementation might look like this:</P><A NAME="auto1074"></A><PRE>    void PMWindowImp::DeviceRect (        Coord x0, Coord y0, Coord x1, Coord y1    ) {        Coord left = min(x0, x1);        Coord right = max(x0, x1);        Coord bottom = min(y0, y1);        Coord top = max(y0, y1);            PPOINTL point[4];            point[0].x = left;    point[0].y = top;        point[1].x = right;   point[1].y = top;        point[2].x = right;   point[2].y = bottom;        point[3].x = left;    point[3].y = bottom;            if (            (GpiBeginPath(_hps, 1L) == false) ||            (GpiSetCurrentPosition(_hps, &amp;point[3]) == false) ||            (GpiPolyLine(_hps, 4L, point) == GPI_ERROR)  ||            (GpiEndPath(_hps) == false)        ) {            // report error            } else {            GpiStrokePath(_hps, 1L, 0L);        }    }</PRE><A NAME="auto1075"></A><P>How does a window obtain an instance of the right<CODE>WindowImp</CODE> subclass?   We'll assume<CODE>Window</CODE> has that responsibility in this example.Its <CODE>GetWindowImp</CODE> operation gets the right instance from anabstract factory (see <A HREF="pat3afs.htm" TARGET="_mainDisplayFrame">Abstract Factory (87)</A>)that effectively encapsulates all window system specifics.</P><A NAME="auto1076"></A><PRE>    WindowImp* Window::GetWindowImp () {        if (_imp == 0) {            _imp = WindowSystemFactory::Instance()->MakeWindowImp();        }        return _imp;    }</PRE><A NAME="auto1077"></A><P><CODE>WindowSystemFactory::Instance()</CODE> returns an abstract factorythat manufactures all window system-specific objects.  For simplicity,we've made it a <A HREF="pat3efs.htm" TARGET="_mainDisplayFrame">Singleton (127)</A> and have let the<CODE>Window</CODE> class access the factory directly.</P><A NAME="knownuses"><A><H2><A HREF="#relatedpatterns"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Related Patterns"></A> Known Uses</H2> <A NAME="auto1078"></A><P>The Window example above comes from ET++ [<A HREF="bibfs.htm#et++" TARGET="_mainDisplayFrame">WGM88</A>]. In ET++, WindowImp is called"WindowPort" and has subclasses such as XWindowPort and SunWindowPort.The Window object creates its corresponding Implementor object byrequesting it from an abstract factory called "WindowSystem."WindowSystem provides an interface for creating platform-specificobjects such as fonts, cursors, bitmaps, and so forth.</P><A NAME="et-use-bridge"></A><P>The ET++ Window/WindowPort design extends the Bridge pattern in thatthe WindowPort also keeps a reference back to the Window. TheWindowPort implementor class uses this reference to notify Windowabout WindowPort-specific events:  the arrival of input events,window resizes, etc.</P><A NAME="stroustrup"></A><P>Both Coplien [<A HREF="bibfs.htm#coplien_idioms" TARGET="_mainDisplayFrame">Cop92</A>] and Stroustrup [<A HREF="bibfs.htm#c++" TARGET="_mainDisplayFrame">Str91</A>] mentionHandle classes and give some examples. Their examples emphasize memorymanagement issues like sharing string representations and support forvariable-sized objects. Our focus is more on supporting independentextension of both an abstraction and its implementation.</P><A NAME="auto1079"></A><P>libg++ [<A HREF="bibfs.htm#libg++" TARGET="_mainDisplayFrame">Lea88</A>] defines classes that implement common datastructures, such as Set, LinkedSet, HashSet, LinkedList, andHashTable.  Set is an abstract class that defines a set abstraction,while LinkedList and HashTable are concrete implementors for a linkedlist and a hash table, respectively.  LinkedSet and HashSet are Setimplementors that bridge between Set and their concrete counterpartsLinkedList and HashTable.  This is an example of a degenerate bridge,because there's no abstract Implementor class.</P><A NAME="libg-bridge"></A><P>NeXT's AppKit [<A HREF="bibfs.htm#NeXT_AppKit" TARGET="_mainDisplayFrame">Add94</A>] uses the Bridge pattern in theimplementation and display of graphical images. An image can berepresented in several different ways. The optimal display of an imagedepends on the properties of a display device, specifically its colorcapabilities and its resolution. Without help from AppKit, developerswould have to determine which implementation to use under variouscircumstances in every application.</P><A NAME="auto1080"></A><P>To relieve developers of this responsibility, AppKit provides anNXImage/NXImageRep bridge. NXImage defines the interface for handlingimages. The implementation of images is defined in a separate NXImageRepclass hierarchy having subclasses such as NXEPSImageRep, NXCachedImageRep, andNXBitMapImageRep. NXImage maintains a reference to one or more NXImageRepobjects. If there is more than one image implementation, then NXImageselects the most appropriate one for the current display device. NXImage iseven capable of converting one implementation to another if necessary. Theinteresting aspect of this Bridge variant is that NXImage can store morethan one NXImageRep implementation at a time.</P><A NAME="relatedpatterns"></A><H2><A HREF="#last"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: navigation"></A> Related Patterns</H2> <A NAME="auto1081"></A><P>An <A HREF="pat3afs.htm" TARGET="_mainDisplayFrame">Abstract Factory (87)</A>can create and configure a particular Bridge.</P><A NAME="auto1082"></A><P>The <A HREF="pat4afs.htm" TARGET="_mainDisplayFrame">Adapter (139)</A>pattern is geared toward making unrelated classes work together.It is usually applied to systems after they're designed.  Bridge,on the other hand, is used up-front in a design to let abstractionsand implementations vary independently.</P><A NAME="last"></A><P><A HREF="#intent"><IMG SRC="gifsb/up3.gif" BORDER=0></A><BR><A HREF="pat4cfs.htm" TARGET="_mainDisplayFrame"><IMG SRC="gifsb/rightar3.gif"	ALIGN=TOP BORDER=0></A> <A HREF="pat4cfs.htm"	TARGET="_mainDisplayFrame">Composite</A><BR><A HREF="pat4afs.htm" TARGET="_mainDisplayFrame"><IMG SRC="gifsb/leftarr3.gif"	ALIGN=TOP BORDER=0></A> <A HREF="pat4afs.htm"	TARGET="_mainDisplayFrame">Adapter</A></P></BODY></HTML>

⌨️ 快捷键说明

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