// Purpose. Flyweight design pattern // 1. Identify shareable state (intrinsic) and non-shareable state (extrinsic) // 2. Create a Factory that can return an existing object or a new object // 3. The client must use the Factory instead of "new" to request objects // 4. The client (or a third party) must compute the extrinsic state import java.awt.*; import java.awt.event.*; import java.io.StringWriter; class FlyweightFactory { private static java.util.Hashtable ht = new java.util.Hashtable(); private static ButtonListener bl = new ButtonListener(); public static Button makeButton( String num ) { if (ht.containsValue( num )) return (Button) ht.get( num ); // 2. Return an existing object Button btn = new Button( num ); // 1. Identify intrinsic state btn.addMouseListener( bl ); ht.put( num, btn ); return btn; // 2. Return a new object } public static void report() { System.out.print( "size=" + ht.size() + " " ); for (java.util.Enumeration e = ht.keys(); e.hasMoreElements(); ) System.out.print( e.nextElement() + " " ); System.out.println(); } } class ButtonListener implements MouseListener { ButtonProxy bp = new ButtonProxy(); public void mouseClicked(MouseEvent e) { Button btn = (Button) e.getSource(); Component[] btns = btn.getParent().getComponents(); int i = 0; for ( ; i < btns.length; i++) if (btn == btns[i]) break; int x = i/ButtonFlyweight.NUM; int y = i%ButtonFlyweight.NUM; String label = btn.getActionCommand(); String s = (new Integer(x)).toString(); String t = (new Integer(y)).toString(); StringWriter sw = new StringWriter(); sw.write(label); sw.write(","); sw.write(s); sw.write(","); sw.write(t); String sendLine = null; if ((e.getModifiers() & e.BUTTON3_MASK) > 0) { //right click happened System.out.println("right click detected"); // System.out.println("label-" + e.getActionCommand() // * + " x-" + i/ButtonFlyweight.NUM + " y-" + i%ButtonFlyweight.NUM ); sw.write(",right"); sendLine = sw.toString(); System.out.println(sendLine); String answer = bp.compute(sendLine); System.out.println("Our result: "+answer); // 1. Identify extrinsic state } else if ((e.getModifiers() & e.BUTTON1_MASK) > 0) { System.out.println("left click detected"); // System.out.println("label-" + e.getActionCommand() // * + " x-" + i/ButtonFlyweight.NUM + " y-" + i%ButtonFlyweight.NUM ); sw.write(",left"); sendLine = sw.toString(); System.out.println(sendLine); String answer = bp.compute(sendLine); System.out.println("Our result: "+answer); } else { System.out.println("weird click detected"); } } public void mouseEntered (MouseEvent e){}; public void mouseExited (MouseEvent e){}; public void mouseReleased (MouseEvent e){}; public void mousePressed (MouseEvent e){}; } class ButtonFlyweight { public static final int NUM = 30; public static final int RAN = 100; public static void main( String[] args ) { Frame frame = new Frame( "Flyweight Demo" ); frame.setLayout( new GridLayout( NUM, NUM ) ); for (int i=0; i < NUM; i++) for (int j=0; j < NUM; j++) // 3. The client must use the Factory to request objects frame.add( FlyweightFactory.makeButton( Integer.toString( (int)(Math.random()*RAN) ) ) ); frame.pack(); frame.setVisible( true ); FlyweightFactory.report(); } } // size=25 24 23 22 21 20 19 18 17 16 9 15 8 14 13 7 12 6 5 11 10 4 3 2 1 0 // label-23 x-0 y-0 // label-7 x-0 y-1 // label-21 x-1 y-1 // label-21 x-4 y-6 // label-7 x-9 y-9