Pattern-Oriented Software Architecture v1巨详细读书笔记 5

本笔记是《Pattern-Oriented Software Architecture vol.1 A system of patterns》原书[page 295-300]的山寨翻译:),包括了View Handler模式的[动态]和[实现]两小节。

-------------------------------------------------

 [动态]

我们选择了2个场景来示例View Handler模式的的行为:视图的创建和排列。两个场景都假定每个视图都显示在他自己的窗口中。
[296]
场景1 显示了View Hanlder如何创建一个新的View,此场景由四个阶段组成:
    - 客户端(可能是用户或者另一个系统组件)调用View Handler打开一个特定的View。
    - View Handler实例并初始化这个View,为实现更改的传播机制,就像Publisher-Subscribe模式一样,此View在其相应的supplier中注册。
    - View Handler将此新的View添加到其内部的已经打开的View列表中。
    - View Handler调用View的函数显示此View,此View打开一个新的窗口,从它的supplier中获取数据,准备这些数据,并把他们呈现给用户。
[图]
场景2 图示了View Handler是如何排列View的,我们简单地假设只有两个视图是被打开的。这个场景被分为三个阶段:
    - 用户执行排列所有已经打开窗口的命令,此请求被发送给View Handler。
    - View Handler计算每个已打开View的大小和位置,并调用他们的resize和move方法。
[297]
    - 每个View都改变自己的位置和大小,设子相应的剪切区域,并刷新它显示给用户的图像。我们这里假定View都缓存了需要显示的图像,如果没有缓存,则View在重新显示它自己之前还需要从他们相关联的supplier中重新获取数据。
[图]


[实现]
实现View Handler的结构由4步骤组成。我们假定supplier已经存在,并且包括了一套适于传播更改的机制。
    1 识别所有的View。识别出需要提供的视图类型,并确定用户如何操控每个独立的View。
    2 描述一个所有View的公共接口,此接口应该包括:打开,关闭,显示,更新和操控view的功能,也可以提供初始化View的功能,用特定的supplier中的数据配置view。将此接口封装进一个抽象类中,可以为例如视图更新这样的功能提供缺省实现。
    在我们的文档编辑器的例子中,定义了类AbstractView,在此类中的protected的方法包括了显示和删除窗口的功能,也包括显示窗口内容的功能,在public方法中包括对View:初始化、打开、关闭、移动、缩放、拖动和更新操作。
[298]
    class Abstractview {
    protected:
        // Draw the view
        virtual void displayData() = 0;
        virtual void displayWindow(Rectang1e boundary) = 0;
        virtual void eraseWindow() = 0;
    public:
        // Constructor and Destructor
        AbstractView ( ) {} ;
        ~AbstractView() { } ;
        // Initialize the view
        void initialize() = 0;
        // View handling with default implementation
        virtual void open(Rectang1e boundary) { /* . . . */ } ;
        virtual void close() ( /* . . . * / };
        virtual void move(Point point) { /* ... */ } ;
        virtual void size(Rectang1e boundary) { /* ... */ } ;
        virtual void drag(Rectang1e boundary) { /* ... */ } ;
        virtual void update () { /* . . . */ } ;
    };
    3 实现每个View。对于每个在第一步骤中识别出的特定类型,都从Abstractview继承一个独立的View类,在特定View中实现如我们例子中的displayData()一样的特定方法,并重写(override)缺省实现不满足需求的方法。
    如果View Handler实现了特定的协调和更新策略,则View必须把所有影响其他View的事件通知给View Handler知道。例如,调整一个View的大小有可能会将之前遮挡到的其他View的某部分显示出来,如果是View Handler来协调这些View的更新,则调整的View应该把此调整事件通知给View Handler知道。Publisher-Subscribe模式能帮助实现这种更改通知机制。
    在解决方案一节我们的例子中,我们实现了3个View类:EditView,LayoutView和ThumbnailView,他们都不需要重写从AbstractView中继承方法的缺省实现。
    4 定义View Handler。可以像Factory Methods模式[GHJV95]一样实现创建View的方法。Client能指定他们所需要的View,但是他们不能控制如何创建View,View Handler负责实例并初始化正确的View组件。
[299]
    View Handler在内部维护所有已经打开的View的引用,Iterator模式[GHJV95]对实现此功能有所帮助。View Handler也许还维护如屏幕上窗口当前位置和大小这样的View附加信息,这些信息在View Handler提供的如窗口克隆这样的管理功能中会用到。
    View Handler也许需要实现应用程序特定的View协调策略,例如,一个View呈现另一个View的信息,动作类似的日志信息。当排列两个相互依赖的View时,需要将他们挨着排放;或者当他们都被最小化的时候,打开一个View将把另一个也打开。
    更新策略是View协作的另一个例子,也许必须优先更新特定View,如:显示告警的View也许需要在打开其他View之前更新,在这种情况下,supplier将改动通知给View handler而不是依赖于他的View,View Handler采取一定的更新策略将此请求转发给受影响的View。协调View更新的View Handler通常在他们的公共接口中提供一个更新函数。
    为了使协作策略能更换,可以采用strategy模式[GHJV95]来实现这些策略。Mediator模式[GHJV95]为实现View协作提供帮助,如:在所有打开的View中广播刷新请求。也可以用Singleton模式[GHJV95]确保View Handler只能被实例化一次。
    在我们的例子文档编辑器中的View Handler提供了打开、关闭、排列、置前、克隆View的功能。在View Handler内部维护了所有已经打开的View的引用,还包括他们的位置和大小、是否已经最小化等信息。
    class ViewHandler {
        // Data structures
        struct ViewInfo {
            Abstractview* view;
            Rectangle boundary;
            boo1 iconized;
        } ;
[300]
        Container<ViewInfo*> myviews;
        // The singleton instance
        static ViewHandler* theViewHandler;
        // Constructor and Destructor
        ViewHandler ( ) ;
        ~ViewHandler();
    public:
        // Singleton constructor
        static ViewHandler* makeViewHandler0 ;
        // Open and close views
        void open (Abstractview* view) ;
        void close(AbstractView* view);
        // Top, clone, and tile views
        void top (AbstractView* view) ;
        void clone(); // Clones the top-most view
        void tile ( ) ;
    } ;

以下代码为创建新View提供示例,defaultBoundary是Rectangle类的对象,定义了每个新窗口的缺省位置和大小,这段代码实现了[动态]一节中的场景一。

    void ViewHandler::openView(AbstractView* view) {
        ViewInfo* viewInfo = new ViewInfo ( ) ;
        // Add the view to the list of open views
        viewInfo ->view = view;
        viewInfo->boundary = defaultBoundary;
        viewInfo->iconized = false;
        myviews.add (viewInfo) ;
        // Initialize the view and open it
        view->initialize () ;
        view->open(defaultBoundary);
    };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值