笔记:Gof设计模式--Bridge

1、意图

  Decouple an abstraction from its implementation so that the two can vary independently.

2、适应性

  Use the Bridge pattern when

  •  you want to avoid a permanent binding between an abstraction and its implementation. This might be the case, for example, when the implementation must be selected or switched at run-time.

  •  both the abstractions and their implementations should be extensible by subclassing. In this case, the Bridge pattern lets you combine the different abstractions and implementations and extend them independently.

  •  changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have to be recompiled.

  •  (C++) you want to hide the implementation of an abstraction completely from clients. In C++ the representation of a class is visible in the class interface.

  •  you have a proliferation of classes as shown earlier in the first Motivation diagram. Such a class hierarchy indicates the need for splitting an object into two parts. Rumbaugh uses the term "nested generalizations" [RBP+91]
to refer to such class hierarchies.

  •  you want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be hidden from the client. A simple example is Coplien's String class [Cop92], in which multiple objects can
share the same string representation (StringRep).

3、结构

 

4、示例代码

  The Window class defines the window abstraction for client applications:

 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& at); 
        virtual void SetExtent(const Point& extent); 
        virtual void Raise(); 
        virtual void Lower(); 
     
        virtual void DrawLine(const Point&, const Point&); 
        virtual void DrawRect(const Point&, const Point&); 
        virtual void DrawPolygon(const Point[], int n); 
        virtual void DrawText(const char*, const Point&); 
     
    protected: 
        WindowImp* GetWindowImp(); 
        View* GetView(); 
     
    private: 
        WindowImp* _imp; 
   View* _contents; // the window's contents 
    }; 



  Window maintains a reference to a WindowImp, the abstract class that declares an interface to the underlying windowing system.

class WindowImp { 
    public: 
        virtual void ImpTop() = 0; 
        virtual void ImpBottom() = 0; 
        virtual void ImpSetExtent(const Point&) = 0; 
        virtual void ImpSetOrigin(const Point&) = 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(); 
    }; 

  Subclasses of Window define the different kinds of windows the application might use, such as application windows, icons, transient windows for dialogs, floating palettes of tools, and so on. For example, pplicationWindow will implement DrawContents to draw the View instance it stores:

 class ApplicationWindow : public Window { 
    public: 
        // ... 
        virtual void DrawContents(); 
    }; 
     
    void ApplicationWindow::DrawContents () { 
        GetView()->DrawOn(this); 
    } 
// IconWindow stores the name of a bitmap for the icon it displays... 
 
 class IconWindow : public Window { 
    public: 
        // ... 
        virtual void DrawContents(); 
    private: 
        const char* _bitmapName; 
    }; 
    
// ...and it implements DrawContents to draw the bitmap on the window:
 void IconWindow::DrawContents() { 
        WindowImp* imp = GetWindowImp(); 
        if (imp != 0) { 
            imp->DeviceBitmap(_bitmapName, 0.0, 0.0); 
        } 
    } 

  Window operations are defined in terms of the WindowImp interface. For example, DrawRect extracts four coordinates from its two Point parameters before calling the WindowImp operation that draws the rectangle in the window:

 void Window::DrawRect (const Point& p1, const Point& p2) { 
        WindowImp* imp = GetWindowImp(); 
        imp->DeviceRect(p1.X(), p1.Y(), p2.X(), p2.Y()); 
    } 


  Concrete subclasses of WindowImp support different window systems. The XWindowImp subclass supports the X Window System:

 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 
    }; 


  For Presentation Manager (PM), we define a PMWindowImp class:

 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; 
    }; 


These subclasses implement WindowImp operations in terms of window system primitives. For example, DeviceRect is implemented for X as follows:

 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); 
    } 
 // The PM implementation might look like this: 
 
 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, &point[3]) == false) || 
            (GpiPolyLine(_hps, 4L, point) == GPI_ERROR)  || 
            (GpiEndPath(_hps) == false) 
        ) { 
            // report error 
     
        } else { 
            GpiStrokePath(_hps, 1L, 0L); 
        } 
    } 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值