1 / 25

The State Design Pattern

The State Design Pattern. Idea: internal state == Object Intent: Allow an object to alter its behaviour when its internal state changes. The object will appear to change its class. State Design Pattern. State Pattern. Motivation : some objects may change their behavior at runtime…

makoto
Download Presentation

The State Design Pattern

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. The State Design Pattern • Idea: internal state == Object • Intent: Allow an object to alter its behaviour when its internal state changes. The object will appear to change its class.

  2. State Design Pattern

  3. State Pattern • Motivation: some objects may change their behavior at runtime… • An individual: Prince / Frog • When kissed, turns into a prince • When cursed, turns into a frog. • If a prince, will go into duel • If a frog, will quack. • Another individual: Dr. Jekyll / Mr. Hyde • At night: will turn into a Mr. Hyde. • At day: will turn into Dr. Jekyll • If Jekyll: cure patients • If Hyde: murder prostitutes • A TCP connection: may be open, may be closed. • A Graphic tool: may be a select tool, but may also be a pen

  4. Typical State Behavior Many of the things you do depend on your state of mind Class C { field f; method task() { if (f == someValue) doTaskOneWay; else if (f == someOtherValue)doTaskInAnotherWay();} method anotherTask() { if (f == someValue) doAnotherTaskOneWay; else if (f == someOtherValue)doAnotherTaskInAnotherWay();} …. }

  5. General Technique: Replacing Conditionals by Inheritance abstractclass A {abstract Type f();} Type Function f() { If (condition) doSomething() else doSomethingElse();} final classIfCondition {final Type f() {doSomething(); }} final classElseCondition {final Type f() {doSomethingElse(); }}

  6. State Pattern • Reaps the “if to inheritance” technique • Useful if many methods exhibit different behavior depending on the same state variables.

  7. Finite Automaton Example a b B a A b b C class Automaton { State currentState = State.initial; State state = State.A; publicvoidop_a(final Automaton context) { state.op_a(context); } publicvoidop_b(final Automaton context) { state.op_b(context); } … } a

  8. State as Enumerated Type Class Automaton { …enum State { A { @Override publicvoidop_a(final Automaton context) { context.state = B; } @Override publicvoidop_b(final Automaton context) { context.state = C; } }, B {…} C {…}; public abstract void op_a(final Automaton context); public abstract void op_b(final Automaton context); }

  9. State Structure Allow a object to alter its behavior when its internal state changes.

  10. State Known Users • Easy to factor out similar strategies (using inheritance)

  11. Example: AVL Tree • AVL Tree: A balanced binary search tree. • Main property: in all nodes • Height of left and right subtrees can differ by at most 1 • Node can be either: • Balanced: same height of left- and right- subtrees • Left tipped: left subtree is higher (by 1) • Right tipped: right subtree is higher (by 1) • Example: tree with only one node. • Node is balanced • The challenge • Insertion of more nodes, while maintaining the AVL property.

  12. An AVL Tree balanced balanced left balanced left right balanced balanced balanced balanced balanced

  13. AVL Insertion Algorithm • Insert: as in ordinary binary search tree. • Balance: traverse the insertion path, bottom up: • Examine subtree: • If height did not increase, stop traversal. • Examine parent (height of subtree changed) • Continue: • Balanced: tip in the appropriate direction. • Stop: • Right inclined and arriving from left, or • Left inclined and arriving from right: • Make parent balanced • Stop traversal • Reorganize and stop: • Right tipping: parent is right inclined and arriving from right, • Left tipping: parent is left inclined and arriving from right: • Make a local reorganization • Stop

  14. AVL Reorganization

  15. AVL Tree Implementation public classAVLTree<T extends Comparable<T>> implements Checkable { Node<T> root; publicAVLTree() { root = null; } publicbooleanisEmpty() { return root == null; } publicvoid clear() { root = null; } … }

  16. Inorder Traversal public classAVLTree … { publicvoidinorder(final Visitor<T> v) { inorder(v, root); } interface Visitor<T extends Comparable<T>> { void visit(T n); } privatevoidinorder(Visitor<T> v, Node<T> n) { if (n == null) return; inorder(v, n.left); v.visit(n.data); inorder(v, n.right); }… }

  17. Tree Invariant public classAVLTree … implements Checkable { @Override publicvoid invariant() { inorder(new Visitor<T>() { T previous = null; @Override publicvoid visit(T current) { if (previous != null) positive(current.compareTo(previous)); previous = current; } }); if (root != null) root.invariant(); } staticclass Node<T extends Comparable<T>> implements Checkable { @Override publicvoid invariant() { … } } }

  18. Node Invariant public class AVLTree …{ staticclass Node<T… > implements Checkable { Node<T> left, right; T data; BalancingState b = BalancingState.BALANCED; @Override publicvoid invariant() {final int hl = height(left); nonnegative(hl); final int hr = height(right); nonnegative(hr); switch (hl - hr) { case 1: sure(b == BalancingState.LEFT); break; case 0: sure(b == BalancingState.BALANCED); break; case -1: sure(b == BalancingState.RIGHT); break; default: unreachable(); } if (right != null) right.invariant(); if (left != null) left.invariant(); } } }

  19. Insertion public classAVLTree …{privatestatic <T…> Node<T> insert(T x, Node<T> n) { if (n == null) return new Node<T>(x); final int comparison = x.compareTo(n.data); if (comparison == 0) // Found in tree, do nothing. return n; if (comparison < 0) n.left = insert(x, n.left); else n.right = insert(x, n.right); return n; } }

  20. Insertion public classAVLTree …{ public void insert(final T x) { if (find(x) != null) // No need for insertion, nor for rebalancing return; root = insert(x, root); … }privatestatic <T…> Node<T> insert(T x, Node<T> n) { if (n == null) returnnew Node<T>(x); finalint comparison = x.compareTo(n.data); if (comparison == 0) // Found in tree, do nothing. return n; if (comparison < 0) n.left = insert(x, n.left); else n.right = insert(x, n.right); return n; } }

  21. Rebalancing public classAVLTree …{ public void insert(final T x) { … root = Defaults.to(balance(root, x), root); }private static <T ….> Node<T> balance(Node<T> n, T x) { comparison = x.compareTo(n.data); if (comparison == 0) // This is the leaf where the node was inserted. return null; if (comparison < 0) { // Node was inserted to the left of this node Node<T> newLeft = balance(n.left, x); if (newLeft == null) // Height of left subtree increased returnn.tipLeft(); n.left = newLeft; return n; } // Node was inserted to the right of this node … }}

  22. Delegation to State public classAVLTree …{staticclass Node<T…> {BalancingState b = BalancingState.BALANCED; Node<T> tipLeft() { returnb.tipLeft(this); } Node<T> tipRight() { returnb.tipRight(this); } }}

  23. Balancing Factor and the State Pattern public classAVLTree …{ staticclass Node<T… > implements Checkable {BalancingState b = BalancingState.BALANCED;enumBalancingState { BALANCED { public <T …> Node<T> tipLeft(Node<T> me) { me.setState(LEFT); returnnull; // height has increased } public <T …> Node<T> tipRight(Node<T> me) { me.setState(RIGHT); returnnull; // height has increased } }, LEFT {…}, RIGHT {…};publicabstract <T…> Node<T> tipLeft(Node<T> n);public abstract <T…> Node<T> tipRight(Node<T> n); }}}

  24. Actions in an Unbalanced Node public classAVLTree …{ staticclass Node<T… > implements Checkable {BalancingState b = BalancingState.BALANCED;enumBalancingState { BALANCED {…}, LEFT {public <T …> Node<T> tipRight(Node<T> me) { returnme.setState(BALANCED); // height did not change } public <T …> Node<T> tipLeft(Node<T> me) { returnme.left.pivotLeft(me); // height did not change } }, RIGHT {…};publicabstract <T…> Node<T> tipLeft(Node<T> n);public abstract <T …B> Node<T> tipRight(Node<T> n); }}}

  25. Delegating Rotation Responsibility classAVLTree { static class Node …{ Node<T> pivotLeft(Node<T> parent) { returnb.pivotLeft(this, parent); }enumBalancingState { BALANCED {…}, LEFT { public <T …> Node<T> tipLeft(Node<T> me) { returnme.left.pivotLeft(me); // height did not change } Node<T> pivotLeft(Node<T> me, Node<T> parent) { // LEFT LEFT balancing } }, RIGHT {…}; <…> Node<T> pivotLeft(Node<T> me,Node<T> parent) { // Default implementation, setting the method contract nonnull(parent); nonnull(me); require(parent.left == me); return parent; } }}}

More Related