0% found this document useful (0 votes)
71 views

Ts-5186 - Design Patterns Reconsidered: Alex Miller Terracotta (Booth 202)

The document discusses design patterns and some of their shortcomings. It summarizes the Singleton, Template Method, Proxy, and Visitor patterns and provides examples of issues with each. It then discusses alternatives and improvements, such as: using interfaces and dependency injection instead of inheritance with Singleton; preferring composition over inheritance for Template Method; avoiding reliance on object identity with Proxy; and using a navigation visitor to address issues with deep inheritance trees in the Visitor pattern.
Copyright
© Attribution Non-Commercial (BY-NC)
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)
71 views

Ts-5186 - Design Patterns Reconsidered: Alex Miller Terracotta (Booth 202)

The document discusses design patterns and some of their shortcomings. It summarizes the Singleton, Template Method, Proxy, and Visitor patterns and provides examples of issues with each. It then discusses alternatives and improvements, such as: using interfaces and dependency injection instead of inheritance with Singleton; preferring composition over inheritance for Template Method; avoiding reliance on object identity with Proxy; and using a navigation visitor to address issues with deep inheritance trees in the Visitor pattern.
Copyright
© Attribution Non-Commercial (BY-NC)
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
You are on page 1/ 56

TS-5186 - DESIGN PATTERNS RECONSIDERED

Alex Miller Terr"c%tt" '(%%th )*)+

http://tech.p re!"#$er.c%& http://terr"c%tt".%r$

,h"t i- " De-i$# P"tter#.


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

2008 JavaOneSM Conference | java.sun.com/javaone |

/G"#$ %0 1% r2 De-i$# P"tter#G"&&"3 4el&3 5%h#-%#3 6li--i!eCrea!ional ( s!rac! )ac!or" Buil#er )ac!or" Me!ho# *ro!o!"pe Sin%le!on S!ruc!ural (#ap!er Bri#%e Composi!e +ecora!or )aca#e )l",ei%h! *ro-" Behavioral Chain of Responsi Comman# $n!erpre!er Me#ia!or Memen!o O server S!a!e S!ra!e%" &empla!e Me!ho# 'isi!or

ili!"

2008 JavaOneSM Conference | java.sun.com/javaone |

The P"tter#- ("c7l"-h


Cop"/pas!e +esi%n " !empla!e Coo/ oo/ / recipe approach

he !esign "atterns solution is to turn the programmer into a fancy macro processor - #. $. !ominus, !esign "atterns Aren%t

2008 JavaOneSM Conference | java.sun.com/javaone |

The P"tter#- ("c7l"-h


+esi%n pa!!erns aren1! pa!!erns Jus! ,or/aroun#s for lan%ua%es missin% fea!ures

At code level, most design patterns are code smells. - &tuart 'alloway

2008 JavaOneSM Conference | java.sun.com/javaone |

The P"tter#- ("c7l"-h


Overuse

(eginning developers never met a pattern or an ob)ect they didn%t li*e. Encouraging them to experiment with patterns is li*e throwing gasoline on a fire. - $eff Atwood, Coding 'orror

2008 JavaOneSM Conference | java.sun.com/javaone |

Pr"ctic"l P"tter#...form a lan%ua%e or voca ular" ...e-pose real issues ...help us compare #esi%n choices

2008 JavaOneSM Conference | java.sun.com/javaone |

A$e#!"
Si#$let%# &empla!e Me!ho# *ro-" 'isi!or

2008 JavaOneSM Conference | java.sun.com/javaone |

There c"# 8e %#l9 %#e...

2008 JavaOneSM Conference | java.sun.com/javaone |

Si#$let%# i# C%!e - thi- i- e"-9:


public final class Singleton { private static Singleton INSTANCE = new Singleton(); private Singleton() { } public static Singleton instance() { return INSTANCE; } public b!ect rea"() { ## nast$ "atabase call return null; } }

2008 JavaOneSM Conference | java.sun.com/javaone |

50

The# thi#$- $% h%rri8l9 ;r%#$ :'


public class Innocent%$stan"er { public voi" so&et'ing() { b!ect foo = Singleton(instance()(rea"(); ## etc((( } } public class TestInnocent%$stan"er { public voi" testSo&et'ing() { ## )a"*oo+s, -ow "o I &oc+ t'e Singleton. } }

2008 JavaOneSM Conference | java.sun.com/javaone |

55

Si#$let%# h"- i-- e6i##en couplin% &es!in% Jus! one7 $!1s a lie. 8volu!ion *ossi le memor" lea/ Su classin% $ni!iali9a!ion or#er an# #epen#encies

2008 JavaOneSM Conference | java.sun.com/javaone |

52

I#ter0"ce- t% the re-c e


public interface Singleton { b!ect rea"(); } public class SingletonI&pl i&ple&ents Singleton { public b!ect rea"() { ## nast$ "atabase call } }

2008 JavaOneSM Conference | java.sun.com/javaone |

53

Depe#!e#c9 i#<ecti%#3 9% =re &9 her%:


public class Innocent%$stan"er { private final Singleton singleton; public Innocent%$stan"er(Singleton singleton) { t'is(singleton = singleton; } public voi" so&et'ing() { b!ect foo = singleton(rea"(); ## etc((( }

2008 JavaOneSM Conference | java.sun.com/javaone |

5.

Ah3 I 0eel cle"# #%;


public class TestInnocent%$stan"er { public voi" testSo&et'ing() { Singleton s = new /oc+Singleton(); Innocent%$stan"er b$stan"er = new Innocent%$stan"er(s); b$stan"er(so&et'ing(); } ## assertions

2008 JavaOneSM Conference | java.sun.com/javaone |

50

,h"t h">e ;e le"r#e! 0r%& Si#$let%#.


$n!erfaces an# #epen#enc" injec!ion Re#uce hi##en couplin% (llo, !es!a ili!" (llo, su classin% Ma/e cons!ruc!ion an# use fle-i le $f nee# onl" one: con!rol " confi%ura!ion no! " pa!!ern ;uice Sprin% B" han# usin% injec!ion

2008 JavaOneSM Conference | java.sun.com/javaone |

52

2008 JavaOneSM Conference | java.sun.com/javaone |

53

A$e#!"
Sin%le!on Te&pl"te Meth%! *ro-" 'isi!or

2008 JavaOneSM Conference | java.sun.com/javaone |

58

Te&pl"te Meth%! ? Pl $$"8le Al$%rith&

2008 JavaOneSM Conference | java.sun.com/javaone |

54

A# ex"&ple i# the ;il! @ Spri#$ M6C


Controller (interface) AbstractController Abstract0rl1iewController 0rl2ilena&e1iewController %aseCo&&an"Controller AbstractCo&&an"Controller Abstract2or&Controller Si&ple2or&Controller Cancellable2or&Controller /ultiActionController 3ara&teri*able1iewController

2008 JavaOneSM Conference | java.sun.com/javaone |

20

Al$%rith& -pel #7i#$

2008 JavaOneSM Conference | java.sun.com/javaone |

25

1i$hti#$ %>er 9% r i#herit"#ce

2008 JavaOneSM Conference | java.sun.com/javaone |

22

Te&pl"te Meth%! h"- i-- e*oorl" #ocumen!s in!en! !o frame,or/ user *u lic vs pro!ec!e# vs a s!rac! me!ho#s )rom #ifferen! levels of inheri!ance hierarch" (l%ori!hm an# or#er of calls Relies on inheri!ance Ma/es composi!ion of func!ionali!" #ifficul! 6ar# !o main!ain an# evolve $nheri!ance hierarch" ma/e comple!el" rea/ #o,n

2008 JavaOneSM Conference | java.sun.com/javaone |

23

Repl"ce i#herit"#ce ;ith c%&p%-iti%#

2008 JavaOneSM Conference | java.sun.com/javaone |

2.

A-e c%#text cl"-- t% exp%-e -t"te

2008 JavaOneSM Conference | java.sun.com/javaone |

20

C"# cl%- re- help.


public class Te&plateAlgorit'& { private {Conte4t=5voi"} step6; public voi" a""Step6({Conte4t=5voi"} bloc+) { t'is(step6=bloc+; } public voi" co&pute() { Conte4t conte4t = new Conte4t(); step6(invo+e(conte4t); step7(invo+e(conte4t); ## &ore steps }

2008 JavaOneSM Conference | java.sun.com/javaone |

22

,h"t h">e ;e le"r#e! 0r%& Te&pl"te Meth%!.


*refer composi!ion !o inheri!ance (llo,s %rea!er reuse Communica!es in!en! e!!er 8asier !o un#ers!an# 8asier !o main!ain More ro us! as i! evolves $nheri!ance is a ver" s!ron% form of couplin% 8speciall" in a sin%le<inheri!ance lan%ua%e

2008 JavaOneSM Conference | java.sun.com/javaone |

23

A$e#!"
Sin%le!on &empla!e Me!ho# Pr%x9 'isi!or

2008 JavaOneSM Conference | java.sun.com/javaone |

28

Pr%x9 hi!e- i#-t"#ce cre"ti%#

2008 JavaOneSM Conference | java.sun.com/javaone |

24

4">e 9% r c"7e "#! e"t it t%%:


public interface Ca+e { voi" eat(); } public class C'ocolateCa+e i&ple&ents Ca+e { public C'ocolateCa+e() { #8 ba+e 8# } public voi" eat() { #8 eat 8# } } public class Ca+e3ro4$ i&ple&ents Ca+e { private Ca+e ca+e; public voi" eat() { ca+e = new C'ocolateCa+e(); ## "ela$e" construction ca+e(eat(); } }

2008 JavaOneSM Conference | java.sun.com/javaone |

30

Pr%8le&: Te!i% - t% ;rite "#! &"i#t"i# -t"tic pr%x9 cl"--epublic class Ca+e-an"ler i&ple&ents Invocation-an"ler { private Ca+e ca+e; public b!ect invo+e( b!ect pro4$9 /et'o" &et'o"9 b!ect:; args) t'rows T'rowable { if(ca+e == null) { ca+e = new C'ocolateCa+e(); } if(&et'o"(getNa&e()(e<uals(=eat>)) { ca+e(eat(); return null; } else { return &et'o"(invo+e(&et'o"9 args); }

S%l ti%# B1: D9#"&ic pr%xie2008 JavaOneSM Conference | java.sun.com/javaone | 35

Pr%8le&: Te!i% - t% ;rite "#! &"i#t"i# -t"tic pr%x9 cl"--eS%l ti%# B): AOP S%l ti%# BC: C%!e $e#er"ti%# Left as an exercise for the reader.... :)

2008 JavaOneSM Conference | java.sun.com/javaone |

32

S%&e %ther i-- e-...


*ro-" fails ,hen rel"in% on o jec! i#en!i!" *ro-" fails ,hen= Su s"s!ems communica!e usin% %eneric in!erface 8ach su s"s!em #o,ncas!s !o more specific /no,n !"pe Reall" a #esi%n pro lem.... u! i! happens +"namic pro-" si#es!eps s!a!ic !"pin% " usin% me!ho# names Coul# use Me!ho#.%e!>ame?@ u! co#e is ver" !e#ious

2008 JavaOneSM Conference | java.sun.com/javaone |

33

,h"t h">e ;e le"r#e! 0r%& Pr%x9.


*ro-" implemen!a!ions have !ra#e<offs 'er osi!" / conciseness S!a!ic !"pin% / !"pe safe!" Main!enance *erformance $#en!i!" is a !ric/" issue in OO s"s!ems Minimi9e reliance on i#en!i!"

2008 JavaOneSM Conference | java.sun.com/javaone |

3.

A$e#!"
Sin%le!on &empla!e Me!ho# *ro-" 6i-it%r

2008 JavaOneSM Conference | java.sun.com/javaone |

30

Oper"ti%#- %>er " C%&p%-ite hier"rch9

2008 JavaOneSM Conference | java.sun.com/javaone |

32

St%ppi#$ 89 0%r " >i-it

2008 JavaOneSM Conference | java.sun.com/javaone |

33

I&ple&e#ti#$ 6i-it%r
public interface 1isitable { voi" accept1isitor(1isitor visitor); } public interface 1isitor { voi" visit(ConcreteNo"e6 no"e6); ## repeat for all concrete no"es } public class ConcreteNo"e6 i&ple&ents 1isitable { public voi" accept1isitor(1isitor visitor) { visitor(visit(t'is); } } public class Concrete1isitor i&ple&ents 1isitor { ## ((( }
2008 JavaOneSM Conference | java.sun.com/javaone | 38

The Expre--i%# Pr%8le& - Philip ,"!ler3 1DD8


(## ne, cases !o a #a!a !"pe (## ne, func!ions over !he #a!a !"pe +on1! recompile ,hen a##in% ei!her cases or func!ions +on1! lose s!a!ic !"pe safe!"

2008 JavaOneSM Conference | java.sun.com/javaone |

34

Pr%8le&: ,here !%e- #">i$"ti%# c%!e li>e.


public class Co&positeNo"e i&ple&ents 1isitable { private ?ist@No"e5 no"es; public voi" accept1isitor(1isitor visitor) { visitor(visit(t'is); for(No"e no"e A no"es) { no"e(accept1isitor(visitor); } }

S%l ti%# B1: I# #%!e2008 JavaOneSM Conference | java.sun.com/javaone | .0

Pr%8le&: ,here !%e- #">i$"ti%# c%!e li>e.


public class Navigation1isitor e4ten"s %ase1isitor { private 1isitor logic1isitor; private ?in+e"?ist@. super 1isitable5 no"eBueue = new ?in+e"?ist@1isitable5(); public Navigation1isitor(1isitor logic1isitor) { t'is(logic1isitor = logic1isitor); } private voi" visitNe4t() { if(,no"eBueue(isE&pt$()) { 1isitable ne4t = (1isitable)no"eBueue(re&ove2irst(); ne4t(accept1isitor(t'is); } }

S%l ti%# B): I# #">i$"ti%# >i-it%r


2008 JavaOneSM Conference | java.sun.com/javaone | .5

Pr%8le&: ,here !%e- #">i$"ti%# c%!e li>e.


public visit(ConcreteNo"e6 no"e) { logic1isitor(visit(no"e); visitNe4t(); } public visit(Co&positeNo"e no"e) { no"eBueue(a""All(no"e(getC'il"ren()); visitNe4t(); } } ## etc

S%l ti%# B): I# #">i$"ti%# >i-it%r


2008 JavaOneSM Conference | java.sun.com/javaone | .2

C%&&%# 6i-it%r T9peACollec!orB visi!or Collec! an# accumula!e for re!urn A)in#erB visi!or Re!urn imme#ia!el" ,hen ma!ch foun# A8ven!B visi!or S!a!eless: fire even!s for su se! of no#es A&ransformB visi!or Mo#if" !he !ree ,hile ,al/in% i! *o!en!iall" #an%erous =@ A'ali#a!ionB visi!or 'erifies !he s!ruc!ure an# repor!s pro lems
2008 JavaOneSM Conference | java.sun.com/javaone | .3

Pr%8le&: Ret r#i#$ " 6"l e


public class Collector1isitor e4ten"s %ase1isitor { private final ?ist@2oo5 collecte" = new Arra$?ist@2oo5(); public ?ist@2oo5 getCollecte"() { return t'is(collecte"; } public voi" visit(ConcreteNo"e6 no"e) { if(s'oul"Collect(no"e)) { collecte"(a""(no"e); } }

S%l ti%# B1: C%llect i# >i-it%r


2008 JavaOneSM Conference | java.sun.com/javaone | ..

Pr%8le&: Ret r#i#$ " 6"l e


public interface 1isitable { @C5 voi" accept1isitor(1isitor@C5 visitor9 C conte4t); } public interface 1isitor@C5 { voi" visit(ConcreteNo"e6 no"e69 C conte4t); ## for all concrete no"es } public class ConcreteNo"e6 i&ple&ents 1isitable { public @C5 voi" accept1isitor(1isitor@C5 visitor9 C conte4t) { visitor(visit(t'is9 conte4t); } }

S%l ti%# B): Ge#eric2008 JavaOneSM Conference | java.sun.com/javaone | .0

Pr%8le&: Ret r#i#$ " 6"l e


public class Concrete1isitor i&ple&ents 1isitor@?ist@String55 { public voi" visit(ConcreteNo"e6 no"e9 ?ist@String5 conte4t) { } conte4t(a""(no"e(getStr());

## e4a&ple use ConcreteNo"e root = ((( Concrete1isitor v = new Concrete1isitor(); ?ist@String5 conte4t = new Arra$?ist@String5(); root(accept1isitor(v9 conte4t);

S%l ti%# B): Ge#eric2008 JavaOneSM Conference | java.sun.com/javaone | .2

Pr%8le&: Excepti%#public class E4ceptional1isitor e4ten"s %ase1isitor { private /$E4ception e4ception; private E4ceptional1isitor() {} public voi" c'ec+Error() t'rows /$E4ception { if(t'is(e4ception ,= null) { t'row e4ception; } } public static voi" run(No"e root) t'rows /$E4ception { E4ceptional1isitor visitor = new E4ceptional1isitor(); root(accept1isitor(visitor); c'ec+Error(); }

S%l ti%# B1: St%re i# C%#crete6i-it%r


2008 JavaOneSM Conference | java.sun.com/javaone | .3

Pr%8le&: Excepti%#public interface 1isitable { @E e4ten"s E4ception5 voi" accept1isitor(1isitor@E5 visitor) t'rows E; } public interface 1isitor@E e4ten"s E4ception5 { voi" visit(ConcreteNo"e6 no"e6) t'rows E; ## for all concrete no"es } public class ConcreteNo"e6 i&ple&ents 1isitable { @E e4ten"s E4ception5 public voi" accept1isitor(1isitor@E5 visitor) t'rows E { visitor(visit(t'is); } }

S%l ti%# B): Ge#eric2008 JavaOneSM Conference | java.sun.com/javaone | .8

C"# cl%- re- help.


Cha! if ,e #efine !he Avisi!B for each !"pe as a closure7 Collec!or visi!or D can collec! in!o local s!a!e of caller )in#er visi!or D use non<local re!urn !o a or! E re!urn 'ali#a!ion visi!or D use non<local re!urn !o a or! E re!urn Simplif" visi!ors ,i!h man" similar me!ho#s +"namicall" assem le ,i!h closures

2008 JavaOneSM Conference | java.sun.com/javaone |

.4

D9#"&ic6i-it%r 8 ilt 0r%& cl%- republic class C$na&ic1isitor i&ple&ents 1isitor { private {ConcreteNo"e6==5voi"} concreteNo"e6%loc+; private {ConcreteNo"e7==5voi"} concreteNo"e7%loc+; private {Co&positeNo"e==5voi"} co&positeNo"e%loc+; public voi" a""ConcreteNo"e6( {ConcreteNo"e6==5voi"} bloc+) { t'is(concreteNo"e6%loc+ = bloc+; } public voi" visit(ConcreteNo"e6 no"e) { if(concreteNo"e6%loc+ ,= null) { concreteNo"e6%loc+(invo+e(no"e); } } } (((

2008 JavaOneSM Conference | java.sun.com/javaone |

00

6i-it%r( il!er
public class 1isitor%uil"er { public static 1isitor%uil"er visitor() { return new 1isitor%uil"er(); } private C$na&ic1isitor visitor = new C$na&ic1isitor(); public 1isitor%uil"er 'an"leConcreteNo"e6( {ConcreteNo"e6==5voi"} bloc+) { visitor(a""ConcreteNo"e6(bloc+); return t'is;

public 1isitor buil"() { return t'is(visitor; }

2008 JavaOneSM Conference | java.sun.com/javaone |

05

A--e&8le
public class Test2in"er { public static No"e fin"/atc'(String na&e9 No"e root) { 1isitor visitor = 1isitor%uil"er(visitor() ('an"leConcreteNo"e6({ConcreteNo"e6 no"e ==5 if(no"e(getNa&e()(e<uals(na&e)) { return no"e; } }) ('an"leConcreteNo"e7({ConcreteNo"e7 no"e ==5 if(no"e(getNa&e()(e<uals(na&e)) { return no"e; } }) (buil"(); root(accept(visitor); return null; } }
2008 JavaOneSM Conference | java.sun.com/javaone | 02

,h"t h">e ;e le"r#e! 0r%& 6i-it%r.


8-pression pro lem is !ou%h !o crac/ Separa!e par!s of !he #esi%n !ha! chan%e a! #ifferen! ra!es ;enerics a## precision an# fle-i ili!" " e-posin% hi##en couplin% Closures provi#e some in!eres!in% ne, possi ili!ies

2008 JavaOneSM Conference | java.sun.com/javaone |

03

De-i$# Pri#cipleFse in!erfaces an# #epen#enc" injec!ion !o re#uce couplin% )avor composi!ion over inheri!ance Separa!e lo%ic !ha! ,ill evolve a! #ifferen! ra!es Rel" on o jec! i#en!i!" as li!!le as possi le Gevera%e s!a!ic !"pin% an# %enerics

2008 JavaOneSM Conference | java.sun.com/javaone |

0.

S &&"r9
+esi%n pa!!erns are a valua le !ool !o #escri e real pro%rammin% pro lems. Solu!ions !o all #esi%n pro lems are con!e-!ual ?#epen#en! on lan%ua%e: !he co#e ase: an# !he #evelopers !hemselves@. Fse #esi%n pa!!erns as a s!ar!in% !o poin! !o #iscuss al!erna!ives. +on1! s!op a! an e-ample from a oo/ or a lo% or even a JavaOne even! presen!a!ion. =@ 8-perimen! !o fin# ,ha! ,ill ,or/ es! for "ouH
2008 JavaOneSM Conference | java.sun.com/javaone | 00

De-i$# P"tter#- Rec%#-i!ere! Alex Miller


http://tech.p re!"#$er.c%&/pre-e#t"ti%#-

2008 JavaOneSM Conference | java.sun.com/javaone |

02

You might also like