0% found this document useful (0 votes)
4 views5 pages

DesignPattern Prototype

The document outlines the implementation of a Prototype Pattern with a Registry for a vector graphics editor, allowing users to create shapes like rectangles and ellipses efficiently by cloning configured prototypes. It discusses the benefits of using prototypes, such as reducing repetitive construction work and enabling dynamic shape registration. Additionally, it covers the importance of deep vs shallow copying and provides guidance on when to use the Prototype versus Factory patterns.

Uploaded by

sanaaara2022
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views5 pages

DesignPattern Prototype

The document outlines the implementation of a Prototype Pattern with a Registry for a vector graphics editor, allowing users to create shapes like rectangles and ellipses efficiently by cloning configured prototypes. It discusses the benefits of using prototypes, such as reducing repetitive construction work and enabling dynamic shape registration. Additionally, it covers the importance of deep vs shallow copying and provides guidance on when to use the Prototype versus Factory patterns.

Uploaded by

sanaaara2022
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Prototype Pattern (with Registry)

Vector Graphics / Diagramming Editor

Context
You are building a vector graphics editor (or diagramming tool) with a palette of tools: Rect-
angle, Ellipse, TextBox, Arrow, etc. Each shape comes with style, constraints, and sometimes
nested parts. Constructing a fully wired shape from scratch can be costly. Users pick a tool
and place many instances of the same kind of shape.

1 Part A — Why Prototype?


1) What pains are we feeling?
• Are shape constructors doing heavy, repetitive work (loading styles, adding handles, attaching
constraints)?
• Do we want to create new shapes by example, not by knowing their concrete class names?
• Can the set of shapes change at runtime (plugins, feature flags), so hard-coding construc-
tors is brittle?

2) What properties do we desire?


• On click, the palette should produce a fresh shape by copying a prototypical instance.
• Creation should be fast and decoupled from concrete types.
• We should be able to add, remove, or reconfigure available shapes without touching
client code.

3) Insight
Keep one configured exemplar per shape type. To create a new instance, clone the exemplar.
Keep those exemplars in a registry (a small in-memory catalog) so tools and frameworks can
request clones by key.

2 Part B — Solution: Prototype + Registry (Shapes)


1) Roles
• Prototype (Shape) exposes copy() (or clone()) to duplicate itself.
• Concrete Prototypes (Rectangle, Ellipse, TextBox) implement copying deep enough for
independence.
• Registry (Prototype Manager) maps keys to prototypes and returns clones.
• Client (Tool/Canvas) asks the registry for a fresh shape to place and then positions it.

1
2) Java sketch (explicit copy(), not Cloneable)

1 // --- Prototype contract ---


2 interface Shape {
3 Shape copy () ; // deep enough for independence
4 void draw ( java . awt . Graphics2D g ) ;
5 void setPosition ( int x , int y ) ;
6 }
7
8 // --- Style value objects ( copied or shared , as appropriate ) ---
9 final class StrokeStyle {
10 final float width ; final boolean dashed ;
11 StrokeStyle ( float w , boolean d ) { this . width = w ; this . dashed = d ; }
12 StrokeStyle copy () { return new StrokeStyle ( width , dashed ) ; }
13 }
14 final class FillStyle {
15 final int rgba ; // ARGB
16 FillStyle ( int rgba ) { this . rgba = rgba ; }
17 FillStyle copy () { return new FillStyle ( rgba ) ; }
18 }
19
20 // --- Concrete prototypes ---
21 final class Rectangle implements Shape {
22 private int x ,y ,w , h ;
23 private final StrokeStyle stroke ;
24 private final FillStyle fill ;
25
26 Rectangle ( int w , int h , StrokeStyle s , FillStyle f ) {
27 this . w = w ; this . h = h ; this . stroke = s ; this . fill = f ;
28 }
29 public Shape copy () {
30 // Copy styles ( immutables could be shared ; copied here for
clarity )
31 return new Rectangle (w ,h , stroke . copy () , fill . copy () ) ;
32 }
33 public void setPosition ( int x , int y ) { this . x = x ; this . y = y ; }
34 public void draw ( java . awt . Graphics2D g ) { /* draw rect with stroke /
fill */ }
35 public String toString () { return " Rect ( " + w + " x " + h + " ) @ ( " + x + " ," + y + " ) " ;
}
36 }
37
38 final class Ellipse implements Shape {
39 private int cx , cy , rx , ry ;
40 private final StrokeStyle stroke ;
41 private final FillStyle fill ;
42
43 Ellipse ( int rx , int ry , StrokeStyle s , FillStyle f ) {
44 this . rx = rx ; this . ry = ry ; this . stroke = s ; this . fill = f ;
45 }
46 public Shape copy () {
47 return new Ellipse ( rx , ry , stroke . copy () , fill . copy () ) ;
48 }
49 public void setPosition ( int x , int y ) { this . cx = x ; this . cy = y ; }
50 public void draw ( java . awt . Graphics2D g ) { /* draw ellipse with
stroke / fill */ }
51 public String toString () { return " Ellipse ( r = " + rx + " ," + ry + " ) @ ( " + cx + " ,
" + cy + " ) " ; }

2
52 }
53
54 final class TextBox implements Shape {
55 private int x , y ; private String text ;
56 private final FillStyle fill ;
57
58 TextBox ( String text , FillStyle f ) { this . text = text ; this . fill = f ; }
59 public Shape copy () { return new TextBox ( text , fill . copy () ) ; }
60 public void setPosition ( int x , int y ) { this . x = x ; this . y = y ; }
61 public void draw ( java . awt . Graphics2D g ) { /* draw text with fill */
}
62 public String toString () { return " TextBox (\" " + text + " \") @ ( " + x + " ," + y +
")"; }
63 }
64

65 // --- Prototype Registry ---


66 final class ShapeRegistry {
67 private final java . util . Map < String , Shape > store = new java . util .
HashMap < >() ;
68
69 public void register ( String key , Shape proto ) { store . put ( key .
toLowerCase () , proto ) ; }
70 public void unregister ( String key ) { store . remove ( key . toLowerCase () )
; }
71 public Shape create ( String key ) {
72 Shape p = store . get ( key . toLowerCase () ) ;
73 if ( p == null ) throw new I l l e g a l A r g u m e n t E x c e p t i o n ( " Unknown : " + key )
;
74 return p . copy () ; // <-- clone the prototype
75 }
76 }
77

78 // --- Client : Palette Tool and Canvas ---


79 final class Tool {
80 private final ShapeRegistry registry ; private final String key ;
81 Tool ( ShapeRegistry r , String key ) { this . registry = r ; this . key = key ; }
82 public Shape onClick ( int x , int y ) {
83 Shape s = registry . create ( key ) ;
84 s . setPosition (x , y ) ;
85 return s ;
86 }
87 }
88
89 class Demo {
90 public static void main ( String [] args ) {
91 ShapeRegistry reg = new ShapeRegistry () ;
92 reg . register ( " rect " , new Rectangle (120 , 80 , new StrokeStyle (2.0
f , false ) , new FillStyle (0 xFF3366CC ) ) ) ;
93 reg . register ( " ellipse " , new Ellipse (60 , 40 , new StrokeStyle (1.5
f , true ) , new FillStyle (0 xAA33CC66 ) ) ) ;
94 reg . register ( " text " , new TextBox ( " Hello " , new FillStyle (0
xFFFFFFFF ) ) ) ;
95
96 Tool rectTool = new Tool ( reg , " rect " ) ;
97 Tool textTool = new Tool ( reg , " text " ) ;
98

99 System . out . println ( rectTool . onClick (100 ,100) ) ; // fresh clone


100 System . out . println ( textTool . onClick (220 ,120) ) ; // fresh clone

3
101
102 // Plugins could : reg . register (" swimlane " , new Swimlane (...) ) ;
103 // And tools can immediately use it without code changes
elsewhere .
104 }
105 }

3) Why this helps (reflection)


• Clients create instances by cloning a configured exemplar; they need no knowledge of con-
structor details.

• Fewer subclasses: many variations become different registered prototypes rather than new
classes.

• The registry lets you add/remove shapes at runtime and inspect what is available.

• Dynamically loaded features can self-register a prototype on load.

3 Part C — Shallow vs Deep Copy & Initialization


Implementing copy() correctly is the most important design decision:

• Decide what is shared vs copied. Immutable style objects can be shared safely; mutable ones
should be copied.

• Complex shapes (composites, constraints, event hooks) often require deep copies or custom
reattachment logic.

• A uniform copy() signature cannot take arbitrary parameters. Common practice: copy
then initialize (e.g., position, text content) via setters or a small initialize(...) method.

4 Part D — When Prototype vs Factories


• Use Prototype when construction is expensive, when objects are better created “by exam-
ple,” or when the set of creatable products changes at runtime.

• Use Factory Method when you have a fixed algorithm that needs to create objects at one
step, and the concrete product varies by subclass of the creator.

• Use Abstract Factory when you must create families of related objects that should be kept
consistent.

• You can implement an abstract factory using a registry of prototypes: each creation method
returns a clone from the registry.

4
5 UML — Prototype with Registry for Shapes

ShapeR
Shape (Prototype)
+ copy(): Shape stores prototypes - map: String
+ draw(g): void + register(key,
+ setPosition(x,y): void + unregister(ke
+ create(key):

Rectangle Ellipse TextBox


Tool / Can
+ copy(): Shape + copy(): Shape + copy(): Shape
... ... ... + onClick(x,y):

You might also like