// Purpose. Lots of client effort to manage a list of Processors public class ChainBefore { interface Image { String process(); } static class IR implements Image { public String process() { return "IR"; } } static class LS implements Image { public String process() { return "LS"; } } static class Processor { private static java.util.Random rn = new java.util.Random(); private static int nextId = 1; private int id = nextId++; public boolean handle( Image img ) { if (rn.nextInt(2) != 0) { System.out.println( " Processor " + id + " is busy" ); return false; } System.out.println( "Processor " + id + " - " + img.process() ); return true; } } public static void main( String[] args ) { Image[] input = { new IR(), new IR(), new LS(), new IR(), new LS(), new LS() }; Processor[] procs = { new Processor(), new Processor(), new Processor() }; for (int i=0, j; i < input.length; i++) { j = 0; while ( ! procs[j].handle( input[i] )) j = (j+1) % procs.length; } }} // Processor 1 - IR // Processor 1 is busy // Processor 2 is busy // Processor 3 is busy // Processor 1 is busy // Processor 2 is busy // Processor 3 - IR // Processor 1 is busy // Processor 2 - LS // Processor 1 - IR // Processor 1 - LS // Processor 1 is busy // Processor 2 is busy // Processor 3 is busy // Processor 1 - LS // Purpose. Chain of Responsibility design pattern public class ChainAfter { interface Image { String process(); } static class IR implements Image { public String process() { return "IR"; } } static class LS implements Image { public String process() { return "LS"; } } static class Processor { private static java.util.Random rn = new java.util.Random(); private static int nextId = 1; private int id = nextId++; private Processor next; public void add( Processor nextP ) { if (next != null) next.add( nextP ); else next = nextP; } public void wrapAround( Processor firstP ) { if (next != null) next.wrapAround( firstP ); else next = firstP; } public void handle( Image img ) { if (rn.nextInt(2) != 0) { System.out.println( " Processor " + id + " is busy" ); next.handle( img ); } else System.out.println( "Processor " + id + " - " + img.process() ); } } static public Processor setUp() { Processor root = new Processor(); for (int i=0; i < 2; i++) root.add( new Processor() ); root.wrapAround( root ); return root; } public static void main( String[] args ) { Image[] input = { new IR(), new IR(), new LS(), new IR(), new LS(), new LS() }; Processor chain = setUp(); for (int i=0; i < input.length; i++) chain.handle( input[i] ); }} // Processor 1 is busy // Processor 2 is busy // Processor 3 is busy // Processor 1 - IR // Processor 1 - IR // Processor 1 is busy // Processor 2 - LS // Processor 1 - IR // Processor 1 is busy // Processor 2 is busy // Processor 3 - LS // Processor 1 is busy // Processor 2 is busy // Processor 3 - LS // Purpose. Chain of Responsibility design pattern // 1. Put a "next" pointer in the base class // 2. The "chain" method in the base class always delegates to the next object // 3. If the derived classes cannot handle, they delegate to the base class abstract class Component { private int value; private Component next; // 1. "next" pointer in the base class public Component( int v ) { this( v, null ); } public Component( int v, Component n ) { value = v; next = n; } public void setNext( Component n ) { next = n; } public void traverse() { System.out.print( value + " " ); } // 2. The "chain" method in the base class always delegates to the next obj public void volunteer() { next.volunteer(); } } class Primitive extends Component { public Primitive( int val ) { this( val, null ); } public Primitive( int val, Component n ) { super( val, n ); } public void volunteer() { super.traverse(); // 3. Primitive objects don't handle volunteer requests 5 times out of 6 if ((int)(Math.random()*100) % 6 != 0) // 3. Delegate to the base class super.volunteer(); } } class Composite extends Component { private Component[] children = new Component[9]; private int total = 0; public Composite( int val ) { this( val, null ); } public Composite( int val, Component n ) { super( val, n ); } public void add( Component c ) { children[total++] = c; } public void traverse() { super.traverse(); // 1 for (int i=0; i < total; i++) // | children[i].traverse(); // +-- 2 } // | | // 3. Composite objects never handle volunteer // | +-- 4 5 public void volunteer() { // requests // | super.volunteer(); // +-- 3 } } // | | // | +-- 6 7 public class ChainDemo { // | public static void main( String[] args ) { // +-- 8 9 Component seven = new Primitive( 7 ); // Component six = new Primitive( 6, seven ); // tra: 1 2 4 5 3 6 7 8 9 Composite three = new Composite( 3, six ); // 4 three.add( six ); three.add( seven ); // 4 5 6 7 Component five = new Primitive( 5, three ); // 4 5 6 7 8 9 Component four = new Primitive( 4, five ); // 4 5 6 7 8 Composite two = new Composite( 2, four ); // 4 5 6 7 two.add( four ); two.add( five ); // 4 5 6 7 8 9 4 5 6 7 Composite one = new Composite( 1, two ); // 4 Component nine = new Primitive( 9, one ); // 4 5 6 7 8 9 4 5 6 7 8 Component eight = new Primitive( 8, nine ); one.add( two ); one.add( three ); one.add( eight ); one.add( nine ); seven.setNext( eight ); System.out.print( "tra: " ); one.traverse(); System.out.println(); for (int i=0; i < 8; i++) { one.volunteer(); System.out.println(); } } } // Purpose. Chain of Responsibility - links bid on job, chain assigns job // // 1. Base class maintains a "next" pointer // 2. Each "link" does its part to handle (and/or pass on) the request // 3. Client "launches and leaves" each request with the chain // 4. The current bid and bidder are maintained in chain static members // 5. The last link in the chain assigns the job to the low bidder public class ChainBidDemo { static class Link { private int id; private Link next; // 1. "next" pointer private static int theBid = 999; // 4. Current bid and bidder private static Link bidder; public Link( int num ) { id = num; } public void addLast( Link l ) { if (next != null) next.addLast( l ); // 2. Handle and/or pass on else next = l; } public void bid() { int num = ((int)(Math.random() * 100)) % 9; System.out.print( id + "-" + num + " " ); if (num < theBid) { theBid = num; // 4. Current bid and bidder bidder = this; } if (next != null) next.bid(); // 2. Handle and/or pass on else bidder.execute(); // 5. The last 1 assigns the job } public void execute() { System.out.println( id + " is executing" ); theBid = 999; } } static Link setUpChain() { Link first = new Link( 1 ); for (int i=2; i < 7; i++) first.addLast( new Link( i ) ); return first; } public static void main( String[] args ) { Link chain = setUpChain(); for (int i=0; i < 10; i++) chain.bid(); // 3. Client "launches & leaves" } } // 1-1 2-6 3-0 4-3 5-1 6-0 3 is executing // 1-1 2-1 3-1 4-0 5-7 6-1 4 is executing // 1-0 2-1 3-0 4-6 5-1 6-2 1 is executing // 1-6 2-3 3-8 4-0 5-1 6-4 4 is executing // 1-8 2-0 3-5 4-8 5-4 6-2 2 is executing // 1-1 2-0 3-8 4-8 5-7 6-0 2 is executing // 1-1 2-1 3-3 4-1 5-6 6-2 1 is executing // 1-2 2-1 3-0 4-3 5-6 6-8 3 is executing // 1-7 2-5 3-4 4-2 5-1 6-2 5 is executing // 1-3 2-6 3-7 4-7 5-6 6-0 6 is executing // Purpose. The number to be factored is passed through a chain of Factor- // Elements until none of them is able to decompose the number any further. import java.io.*; public class ChainContrib { static class Memento { private boolean[] done; private int sp = 0; private int[] factors = new int[10]; public Memento( int num ) { done = new boolean[num]; } public void add( int n ) { factors[sp++] = n; } public void setDone( int i ) { done[i] = true; } public boolean isDone() { for (int i=0; i < done.length; i++) if ( ! done[i]) return false; return true; } public String toString() { StringBuffer sb = new StringBuffer(); for (int i=0; i < sp; i++) { sb.append( factors[i] ); sb.append( ' ' ); } sp = 0; for (int i=0; i < done.length; i++) done[i] = false; return sb.toString(); } } static class FactorElement { private int index, divisor; private FactorElement next; private static Memento mem; public FactorElement( int i, int d, FactorElement fe ) { index = i; divisor = d; next = fe; } public void setNext( FactorElement fe ) { next = fe; } public String getResults() { return mem.toString(); } public void getFactors( int[] num ) { if (num[0] % divisor == 0) { mem.add( divisor ); num[0] = num[0] / divisor; } else mem.setDone( index ); if ( ! mem.isDone()) next.getFactors( num ); } public static FactorElement setUp() { int[] divisors = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 }; int size = divisors.length; mem = new Memento( size ); FactorElement last = new FactorElement( size-1, divisors[size-1], null ); FactorElement current = last; for (int i=size-2; i > -1; i--) current = new FactorElement( i, divisors[i], current ); last.setNext( current ); return current; } } public static void main( String[] args ) throws IOException { BufferedReader rdr = new BufferedReader( new InputStreamReader( System.in )); int[] num = new int[1]; String str; FactorElement root = FactorElement.setUp(); while (true) { System.out.print( "Enter number: " ); str = rdr.readLine(); if (str.equals("0")) break; num[0] = Integer.parseInt( str ); root.getFactors( num ); System.out.println( " " + root.getResults() + "- " + num[0] ); } }} // Enter number: 30 // 2 3 5 - 1 // Enter number: 31 // 31 - 1 // Enter number: 32 // 2 2 2 2 2 - 1 // Enter number: 127 // - 127 // Enter number: 60 // 2 3 5 2 - 1 // Enter number: 180 // 2 3 5 2 3 - 1 // Enter number: 216 // 2 3 2 3 2 3 - 1 // Enter number: 2310 // 2 3 5 7 11 - 1 // Enter number: 4620 // 2 3 5 7 11 2 - 1 // Enter number: 13860 // 2 3 5 7 11 2 3 - 1 // Enter number: 0