界面模式一览 UI Patterns at a Glance

rubiks cube - empty Recently, I have started to do a lot of UI coding. Switching from server coding to UI development is a big step. Thanks to these patterns, they do make my transit smooth.

1. MVC - a pattern needs no introduction

You heard about it more than enough. Yet, many can not tell the essence of MVC and how they interact. A diagram is worth a thousand words, especially from Jack ;)

image 

[COPYRIGHT: JACK LI & WILEY PUBLISHING (c) 2004, 2008]
 

2. Action - a central controller for a command with multiple invoking UI controls

Scenario: You are developing a word processor. When some text is selected, the 'copy' icon at the toolbar is enabled as well as the menu Edit -> Copy. The action copy has two invoking UI controls, the toolbar item and the menu item.

Solution: Use the Action class as the controller to coordinate the command function and UI controls.

public class Action {
  var listOfUIs:ArrayCollection = new ArrayCollection();

  var label:String;
  var icon:Class
  var func:Function;

  // Creates a new button to be added to the toolbar
  public function createNewToolbarItem():Button {
    var ui:Button = new Button();
    ui.label = this.label;
    ui.setStyle("icon", icon);
    ui.addEventListener(MouseEvent.CLICK, func);
    listOfUIs.add(ui);
    return ui;
  }
 
  // Creates a new menu item to be added to the toolbar
  public function createNewMenuItem():UIComponent {
    ...
  }

  // Enables/disables the action as well as all related UIs.
  public function enabled(enable_:Boolean):void {
    for each ui in listOfUIs {
      ui.enabled = enable_;
    }
  }
}

Usage:

var actionCopy:Action = new Action():
actionCopy.label = "Copy";
actionCopy.icon = ...;
actionCopy.func = doCopy;

toolbar.addChild(actionCopy.createNewToolbarItem());
menubar.addChild(actionCopy.createNewMenuItem());

actionCopy.enabled = false; // initially enable it.
...

// to be called when text selection changes
private function void onTextSelectionChange(e:TextSelectionEvent):void {
  actionCopy.enabled = e.selectedText != null;
}

Note: Above code demonstrates the very basic implementation of the Action pattern. For a completed production implementation, see Java Swing's Action.

 

3. Image Registry - a central repository for resource sharing and management 

Scenario: we need to display the same image multiple times at different places. For example, we want to add the same icon to every single submit button in any form.

Solution: two requirements: (1) re-use of image data; (2) dynamic loading from external sources

Skeleton:

public class ImageRegistry {
  var baseURL:String;
  
  public function getImage(path:String):Image {
    ...
  }
}

The magic all happens in the getImage method. You should check whether the given path has been loaded, if so re-use it to create new images. If the path has not been loaded, send requests to the server. If you need a reference implementation, see SWT/JFace's ImageRegistry/FontRegistry.


Well, patterns are useful for providing a guided analysis on a particular problem. They're not libraries neither utilities. Sure, it is challenging to implement all of them in AS3. However, by keeping these ideas in mind, you can write good programs that perform well.