2. Design patterns. part #2

Post on 07-Jul-2015

499 views 1 download

Tags:

description

Since these presentations were spare time hobby - I've decided to share them :) Hopefully someone will find them useful. This part continues 1. part with more design patterns like Command, State, NullObject.

Transcript of 2. Design patterns. part #2

Leonid M.

Design Patterns- Command

- State

- NullObject

Puzzle questions

Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice

Christopher Alexander, Sara Ishikawa, MurraySilverstein, Max Jacobson,Ingrid Fiksdahl-King, and Shlomo Angel.A Pattern Language. Oxford

University Press, NewYork, 1977.

Synonyms: Action, Transaction

Intent: Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

There are two extremes that a programmer must avoid when using this pattern:

1. The command is just a link between the receiver and the actions that carry out the request

2. The command implements everything itself, without sending anything to the receiver.

We must always keep in mind the fact that the receiver is the one who knows how to perform the operations needed, the purpose of the command being to help the client to delegate its request quickly and to make sure the command ends up where it should.

Command decouples the object that invokes the operation from the one that knows how to perform it.

Commands are first-class objects. They can be manipulated and extended like any other object.

You can assemble commands into a composite command.

It's easy to add new Commands, because you don't have to change existing classes.

Application

add(Document)

Menu

Menu Item

onClick()

Action

Save Command

execute()command->execute()

document->save()

import java.awt.Component;import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;import javax.swing.JFrame;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JOptionPane;

class ExitAction extends AbstractAction {public ExitAction() {

super("exit");}

public void actionPerformed(ActionEvent e) {System.exit(0);

}}

class ShowDialogAction extends AbstractAction {public ShowDialogAction() {

super("show dialog");}

public void actionPerformed(ActionEvent e) {JOptionPane.showMessageDialog((Component) e.getSource(),

"An action generated this dialog");}

}

public class Test extends JFrame {public static void main(String args[]) {

Test frame = new Test();frame.setTitle("Swing Actions");frame.setSize(500, 400);frame.setLocation(400, 200);frame.show();

}

public Test() {JMenuBar mb = new JMenuBar();JMenu fileMenu = new JMenu("File");fileMenu.add(new ShowDialogAction());fileMenu.add(new ExitAction());

mb.add(fileMenu);setJMenuBar(mb);

}}

Undo support

Macro-commands

Queuing requests

Logging requests

Command manager

Command Command

Please, undo the last one. It caused problems!

client

Can undo? Take back, undo, place in queue

-addCommand()-undo()

-execute()-canUndo()-undo()

DrawHouse

PaintRectangle

PaintLine

PaintLine

PaintLine

PaintLine

FillRectangle…

FillRectangle…

/**

* Calculates the proper constraint for a child being added. createAddCommand is called afterwards.

*/

@Override

protected Command getAddCommand(Request generic) {

// cast request to ChangeBoundsRequest

ChangeBoundsRequest request = (ChangeBoundsRequest) generic;

// get all Edit Parts of request

List editparts = request.getEditParts();

// create a new CompoundCommand

CompoundCommand res = new CompoundCommand();

Rectangle r;

Object constraint;

// for each Edit Part set constraint

for (Iterator epIt = editparts.iterator(); epIt.hasNext();) {

GraphicalEditPart part = (GraphicalEditPart) epIt.next();

r = part.getFigure().getBounds().getCopy();

// convert r to absolute from childpart figure

part.getFigure().translateToAbsolute(r);

r = request.getTransformedRectangle(r);

// convert this figure to relative

getLayoutContainer().translateToRelative(r);

getLayoutContainer().translateFromParent(r);

r.translate(getLayoutOrigin().getNegated());

constraint = getConstraintFor(r);

if ((part instanceof AttributeEditPart) || (part instanceof MethodEditPart)

|| (part instanceof SlotEditPart)) {

return null;

} else {

res.add(createAddCommand(part, constraint));

}

}

return res.unwrap();

}

DrawHouse

PaintRectangle

PaintLine

PaintLine

PaintLine

PaintLine

FillRectangle

FillRectangle …

Command

Command

Command

Thread

Thread

ThreadThread

Thread

User commands are added to the queue

This gives an effective way to limit computations to a fixed numbers of threads

Threads removes commands from the queue by on one, calls execute(). Once complete, go back for a new command object

java.lang.Runnable- Sample invoker: SwingUtilities.invokeLater()

java.util.concurrent.Callable<V>- Sample invoker: ExecutorService#submit(),

ExecutorService#invokeXxxx()

execute()execute()

execute()

store()

store()

store()

execute()execute()

execute()

load()

load()

load()

Also Known as:Stub, Active Nothing

Intent: - Provide an object as a surrogate for the lack of an object of a given

type.

- The Null Object Pattern provides intelligent do nothing behavior, hiding the details from its collaborators.

Null objects can be used in place of real objects when the object is expected to do nothing.

Makes client code simple. (reduces branching)

Encapsulates the do nothing code into the null object.

Makes the do nothing code in the null object easy to reuse.

Makes the do nothing behavior difficult to distribute or mix into the real behavior of several collaborating objects.

Can be difficult to implement if various clients do not agree on how the null object should do nothing as when your AbstractObject interface is not well defined.

Always acts as a do nothing object. The Null Object does not transform into a Real Object.

Null Object and FactoryThe Null Object design pattern is more likely to be used in conjunction with the Factory pattern. The reason for this is obvious: A Concrete Classes need to be instantiated and then to be served to the client. The client uses the concrete class. The concrete class can be a Real Object or a Null Object.

Null Object and Template MethodThe Template method design pattern need to define an abstract class that define the template and each concrete class implements the steps for the template. If there are cases when sometimes template is called and sometimes not then, in order to avoid the checking a Null Object can be use to implement a Concrete Template that does nothing.

Removing old functionalityThe Null Object can be used to remove old functionality by replacing it with null objects. The big advantage is that the existing code doesn't need to be touched.

NullAppender (log4j)

java.util.Collections (jdk)- #emptyList()

- #emptySet()

- …

NullIterator (jdk, internal structures)

public class NullIterator<E> implements Iterator<E> {

@Overridepublic boolean hasNext() {

return false; // Null implementation returns false indicating iterator is empty}

@Overridepublic E next() {

throw new NoSuchElementException("Null iterator doesn't contain anything");}

@Overridepublic void remove() {

throw new UnsupportedOperationException("Null iterator doesn't support remove operration");}

}

Application: Email spam filtering system. Both HTML and Text formats should be supported.

Multiple spam recognition algorithms are present and several could be used simultaneously.

Multiple weekly report approaches should be supported: XML, HTML files on filesystem;+ email with report attachment.

Do You see a need for the Command, NullObject design patterns?

Is Your vision changed somehow?

- How does it change Your design?

- What new considerations come up to mind?

- How do these changes impact application?

- How do these impact possible request changes?