1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the...

56
Session 1937 Beyond Actions Brian Sletten System Architect Parabon Computation, Inc. A Semantically Rich Command Pattern for the Java™ Foundation Classes (JFC/Swing) API

Transcript of 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the...

Page 1: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 1937

Beyond Actions

Brian SlettenSystem ArchitectParabon Computation, Inc.

A Semantically Rich Command Pattern for the Java™ Foundation Classes (JFC/Swing) API

Page 2: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 19372

Overall Presentation Goal

Learn a low-risk way to take advantage of a richer Command pattern in applications using the Java™ Foundation Classes (JFC/Swing) API

Page 3: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 19373

Learning Objectives

• As a result of this presentation, you will understand:– The limitations of conventional GUI

development– The limitations of the Action Interface– The Command Design Pattern– How to fold this into your code gradually

and with minimal risk– The basics of Aspect-Oriented Programming

Page 4: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 19374

Speaker’s Qualifications

• Brian Sletten is a System Architect at Parabon Computation, Inc.

• Has a background in user interface and visualization frameworks

• Has used the Command Pattern for eight years with C/C++, Java™ technology and X/Motif

• Former OOAD-certified instructor

Page 5: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 19375

Presentation Agenda

• Review: How GUIs Are Built

• Action Interface

• Review: Design Patterns

• Command Pattern

• Making it Happen with JFC/Swing technology

• Happy Consequences

Page 6: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 19376

Review: How GUIs Are Built

• Components are laid out– Visually– Programmatically

• Event handlers are registered to call code– The “guts” of an application– Not-so-Good-Old-Days: callbacks – Now: EventListener Objects

Page 7: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 19377

Sample Event Handler

class MyActionListener implements ActionListener

{public void actionPerformed( ActionEvent ae ) {System.out.println( “You pressed me!” );

}}

JButton pressMe = new JButton( “Press Me” );ActionListener myAL = new MyActionListener();pressMe.addActionListener( myAL );

Page 8: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 19378

What is Wrong With This Approach?

• Hard to add additional invokers– JButtons, JMenuItems, etc.

• Difficult to modify invoker/listener binding– Was JButton, now JList

• Listener is often “dumb” code– Often calls other objects to do real work– Almost impossible to undo behavior– Cannot enable/disable behavior, only

components

Page 9: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 19379

What is Wrong With This Approach? (Cont.)

• Heterogeneous event system hard to unify

• Anonymous inner classes are convenient but make it worse– Anonymity is real!– No way to refer to that code elsewhere

• AWT/Swing specific– Other UI toolkits exist

• MIDP as part of the J2ME™ platform• SWT at http://www.eclipse.org

Uses its Own Command!!

Page 10: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193710

What About Action Interface?

Action cutAction = new CutAction();JButton cutButton = new JButton( cutAction );cutAction.setEnabled( false );...class CutAction extends AbstractAction {

public CutAction() {super( “Cut” );

}

public void actionPerformed( ActionEvent ae ) {..}

}

Page 11: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193711

Action Interface Benefits

• Step in the right direction– Eliminates a lot of “dumb code”

• Supports multiple invokers

• JButtons, JMenuItems, etc. handle– Glue code– Shared instances

• Enabledness support– Disable the Action, disable the components

Page 12: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193712

Action Interface Limitations

• Only supports ActionListener!– Did we suddenly forget about

all of the other events and components in the JFC API?

• Needs more abstraction

• No state management

• No support for Undo– Other than UndoManager

Page 13: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193713

Design Patterns

• Solutions to common design problems in a particular context

• An attempt to reuse design, not just code

• Does not eliminate design effort, makes it– Simpler– Cleaner– More robust

Page 14: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193714

How to Get Started with Patterns

• Read Design Patterns [GOF95]

• Look at other examples online

• Pick one that seems appropriate and try it

• Keep in mind:– Use only where appropriate– Don’t force it

Page 15: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193715

Command Pattern

• A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested or the caller’s identity

• Eh?

• Key Points

– Parameterized request to an Object

– Request is an Object

– Loose coupling between caller and receiver

• JButton is unaware of ultimate action or receiver

Page 16: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193716

Command Pattern: Parameterized

• Command maintains its own state or invokes methods on “Receiver” objects– Specific to concrete instance– Ways to parameterize commands

OpenDocumentCommand odc = new OpenDocumentCommand( new Document() );

odc.execute(); // executes on document receiver

OpenWindowCommand owc = CommandFactory.getCommand( “Open Window” );

owc.setValue( w );owc.execute(); // executes on Window receiver

or

Page 17: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193717

Command Pattern : Loose Coupling

• Command objects do not care who invokes them– Component– Other Command– Macro playback script

Button Invoker

Page 18: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193718

Command Pattern :Loose Coupling (Cont.)

Macro Playback Invoker

Page 19: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193719

Command Pattern: Class Diagram

Command “Receiver”

JButton, JList, other components

Concrete Commands

Page 20: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193720

Question

Is the ActionListener an example of the Command Pattern?

Page 21: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193721

XLoose Coupling

√Request is an Object

XParameterized

Answer: No

Page 22: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193722

ActionListener is an Observer Pattern

• Concrete subjects notify concrete observers at an abstract level without coupling

• Also seen in Model-View-Controller (MVC)

JButtonActionListener

Watches

Page 23: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193723

Making it Happen With JFC/Swing Technology

• Goals

• Basic Design

• Helper Classes

• Introduction: Aspect-Oriented Programming

• Using AOP for Commands

Page 24: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193724

Goals

• Low Buy-In Cost

• Basics are basic

• Mechanism, Not Policy– Extensible– Flexible

Page 25: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193725

Basic Design

• Enabledness– setEnabled( boolean value )– boolean getEnabled()

• Dependencies– addDependency(Command cmd )

• Indication of Undo support– canUndo()

• State management– pushState(CommandState state)– CommandState peekState()– CommandState popState()

Page 26: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193726

Command Responsibilities

• Must be named

• Provide an execute() body

• To support undo() should manage its own state– Indicates capability with canUndo()– pushState(), peekState(), popState()

are helpful, but not required

Page 27: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193727

Command Features

• Support PropertyChangeListeners– Observer Pattern!

• Enabledness support– Disabled Commands cannot be executed– Fires propertyChangeEvent

• Supports dependent Commands

Page 28: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193728

Command Features (Cont.)

• Value semantics are available if they are helpful to the Command– void setValue( Object value )– Object getValue()

• Guideline: – Document the Command’s value

expectations and do not abuse lack of type-safety!

Page 29: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193729

CommandFactory

• Organizing point for Commands

• Static methods to add/get Commandsby name

Page 30: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193730

CommandGlue

• Helper class to handle hooking the Commands to components based on type

• Default glue code per component– Marginally subjective– Configurable via file

• Simple for basic mappings

Page 31: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193731

CommandGlue (Cont.)

• Client code can request Command firing for non-default event for flexibility

• Invoker must support the appropriate interface

√√

FocusListener

√XJList

X√JButton

ListSelectionListenerActionListener

Page 32: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193732

Simple App

Page 33: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193733

Introduction: Aspect-Oriented Programming

• A new approach to software development– Works with OOP, does not replace OOP

• OOP organizes classes on relational boundaries– Mostly up vertical hierarchies

• Problem arises when desired behavior touches lots of classes

Page 34: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193734

OOP Inheritance is Good For…

Behavior along verticalrelationships

Page 35: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193735

OOP Inheritance is Not As Good For…

Behavior that crosses horizontal boundaries

Page 36: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193736

Cross-Cutting Concerns

• Behavior that applies across horizontal layers– Logging/Tracing– Thread synchronization– Security

• Behavior needs to be pushed up the hierarchy– Base classes become fat and hard to change!

Page 37: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193737

Modularize Cross-Cutting Concerns

• AOP’s goal: Modularize cross-hierarchy behavior– Easier to maintain– Easier to extend– Compile it in, compile it out

Page 38: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193738

AspectJ and Pointcuts

• AspectJ is an AOP tool for the Java™ platform

• Allows you to define pointcuts– Places in the code during an execution– A little bit like a debugging breakpoint

• “Advice” is the term applied to code that gets run at a breakpoint

• Specify pointcuts with patterns

Page 39: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193739

Pointcut Example

aspect FooSet {

// specifies any call to a method that begins// with the word “set” in class Foo

pointcut setPointCut() :call( public void Foo.set*(*) );

before() : setPointCut() {System.out.println( “You’re about to set!”

);}after() : setPointCut() {

System.out.println( “You just set!” );}

}

Page 40: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193740

More AspectJ

• Aspects and relevant classes get compiled like classes using the ajc compiler

• The magic happens during “compile-time” weaving of pointcut advice

• For more details: – http://www.aspectj.org

Page 41: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193741

Using AOP for Commands

• We want to use AOP where it will help, not just because it is cool– Command Glue

• hook Commands to components– Undo/Redo

• state management before/after execute()

• AOP isn’t necessary, but it is elegant

Page 42: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193742

Gluing Commands with Aspects

pointcut glue( JComponent jc, Object key, Object value ) :

call( void putClientProperty( *, * ) ) &&args( key, value ) && target( jc );

// allows advice to be specified for:JButton clearButton = new JButton();clearButton.putClientProperty(

Command.COMMAND_NAME_PROPERTY, “clear_cmd” );

The “glue” pointcut occurs here

Page 43: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193743

Gluing Commands with Aspects (Cont.)

after( JComponent jc, Object key, Object value ) : glue( jc, key, value ) {if(key.equals(Command.COMMAND_NAME_PROPERTY)) {

CommandGlue.setCommand( jc, ( String ) value );

}}

This after advice for the “glue” pointcut connects JComponents to named Commands via default EventListener

Page 44: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193744

Undo/Redo

• Different policies for this behavior

• Defining the policy at Command level will make it harder to change

• It’s still difficult to apply to all Commands (especially ones we don’t write!)

Page 45: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193745

Undo Pointcut

pointcut commandExecuted( Command cmd ) : call( void Command.execute() ) &&target( cmd ) && !target( UndoCommand ) &&!target( RedoCommand );

Target is a Command, but not the UndoCommand or RedoCommand

Whenever execute is called on a Command object (and descendants!)

Page 46: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193746

Undo Advice

after( Command cmd ) : commandExecuted( cmd ) {String undoName =

UndoCommand.DEFAULT_NAME; UndoCommand undoCmd = ( UndoCommand )

CommandFactory.getCommand( undoName );

undoCmd.setValue( cmd );}

UndoCommand’s value is interpreted as last executed Command

Get the UndoCommand from CommandFactory

Page 47: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193747

Happy Consequences

• Other features almost fall out of the Command Pattern – Application Auditing– Macro Record/Playback– Role-based Capabilities

Page 48: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193748

Application Auditing

• Auditing is simply half of Macro recording

• Establish recording mechanics– File system, RMI server, encryption, etc.

• Create after() advice for Command execution– Capture Command name and timestamp

Page 49: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193749

Macro Record/Playback

• Another cross-cutting concern that would complicate the Command base class and might not be used

• Using aspects allows us to localize this behavior– Introduce capabilities over time– Apply as needed– Change behavior easily

Page 50: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193750

Role-based Capabilities

• Java™ Authentication and Authorization Service (JAAS) API associates Identities with credentials

• Consider combinations of Commands, aspects and Identities– Map Command names to credentials

• CHANGE_CONFIG requires Role(Operator)• VIEW_CONFIG requires Role(Any)

– Enable capabilities at login time• Perhaps a LoginContext.login() pointcut

– Check permissions in around() advice on execute() pointcut

Page 51: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193751

Come Together

• The JFC/Swing API is a rich toolkit!• Much can be done to improve Java

technology UI apps– Commands– Application frameworks– Reusable components– New capabilities

• Check out: – http://www.swingcommunity.org

Page 52: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193752

Summary

• Command Design Pattern opens many possibilities for JFC/Swing API-based apps

• Easy to incorporate gradually– No big buy-in required

• AOP is an implementation decision here– Offers elegant expression of ideas– Modularizes cross-cutting concerns– Keeps the base classes lighter– Not strictly necessary

Page 53: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193753

If You Only Remember One Thing…

Mixing Java™ Foundation Classes (JFC/Swing) technology with creative design approaches can unleash exciting new features

Page 54: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 193754

Suggested Reading

[GOF95] Design Patterns, Erich Gamma, Richard Helm, Ralph Johnson, 1995. Addison-Wesley

[Grosso01] For a non-UI use of Command Pattern: http://www.onjava.com/pub/a/onjava/2001/10/17/rmi.html

[Metsker02] The Design Patterns Java™ Workbook, Steven J. Metsker, 2002. Addison-Wesley [Published this spring]

[Young92] Object-Oriented Programming w/C++ and OSF/Motif, Douglas A. Young, 1992. Prentice Hall

More references

Page 55: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 1937

Page 56: 1937 Sletten D 1 - pietschy.com · Command Pattern • A Design Pattern to allow the parameterization of a request to an object without special knowledge of the operation requested

Session 1937