Design Patterns
SINGLETON OG STRATEGY
Jakob Majkilde: lotusscript.dk | xpages.dk | notesnet.dk/majkilde
Patterns – hvorfor nu det?
Genbrug andre erfaringer
Bedre struktur – og genkendelig struktur
Ingen grund til at opfinde tallerkenen igen
Patterns til det hele
Create
◦ Factory, Builder, Object Pool, Prototype, Singleton
Structure
◦ Adapter, Bridge, Composite, Decorator, Facade, Flyweigth, Private Class Data, Proxy
Behavior
◦ Chain of responbility, Command, Interpretor, Iterator, Mediator, Memento, Null Object, Observer, State,
Strategy, Template method, Visitor
Demonstration
Hvordan får du 2 knapper til at dele samme kode/variable på en Notes form?
Og hvordan vil du gøre hvis de sidder på hver sin SubForm?
Singleton
Sikre at der kun er én instance af klassen (ét object)
Regel #1: Vi bruger aldrig globale variable!
◦ Der er dog én undtagelse i Lotus Script: Execute
Har selv brugt det til bl.a.
◦ getWorkflow
◦ getAttachmate
◦ getLog
Sub Initialize
getLog().print( "Hello" )
dim f as New Foo()
call f.run()
End Sub
Class Foo
Sub run()
getLog().print( "Running..." )
End SUb
End Class
Lotus Script Singleton
Uanset om getFoo() kaldes fra en knap, en subform eller PostOpen event, så returneres det
samme object.
Public function getFoo() As Foo
Static fooSingleton As Foo
If fooSingleton Is Nothing Then
Set fooSingleton = New Foo()
End If
Set getFoo = fooSingleton
End function
Java Singleton
Samme som i Lotus Script
◦ Bare lidt mere elegant
◦ Alt er samlet i én klasse
◦ Private constructor sikre mod forkert brug
Thread safe / Unit Test? Google it:
◦ Stackoverflow.com/questions/6088195/
factory-for-thread-safe-singleton-in-java
Serialization? Google it:
◦ javadata.blogspot.dk/2011/12/
singleton-and-serialization.html
Factory pattern?
◦ Oplagt – men det bliver næste gang …
public class Foo {
private static Foo fooSingleton = new Foo();
private Foo() {}
public static Singleton getInstance() {
return fooSingleton;
}
}
Demonstration
Et CRM system i Notes
◦ Klassisk response hierarki i Notes.
◦ Hoveddokumentet er ‘Company’
◦ Kan være én af 2 typer: ‘Kunde’ el. ‘Emne’
◦ Der er kun én Main Form.
◦ Der bruges hide/when til at styre forskellen mellem Kunde og Emne
Back-end script
◦ Class: Company
◦ Recalc genberegner skjulte felter
◦ isValid checker om data er ok
Hvorfor er det et dårligt design?
Company
Contact
Document
Company
+ create
+ delete
+ recalc
+ isValid
• Der tilføjes nye firma typer:
Leverandør, Entreprenør, Forhandler, Sama
rbejdspartner, …
• If…then…else konstruktion skal opdateres i
både create, delete, recalc og isValid
metoder
• Koden bliver kompleks og uoverskuelig
• Ændringer giver nemt følgefejl
• Svært at teste og debugge
Nyt design
En klasse til hver firma type
Hvorfor kan det være et dårligt design?
Company
+ create
+ delete
+ recalc
+ isValid
Customer
+ create
+ delete
+ recalc
+ isValid
Supplier
+ create
+ delete
+ recalc
+ isValid
Lead
+ create
+ delete
+ recalc
+ isValid
XXX
+ create
+ delete
+ recalc
+ isValid
Local
+ create
+ delete
+ recalc
+ isValid
International
+ create
+ delete
+ recalc
+ isValid
• Koden bliver hurtigt ‘fragmenteret’ – en local
supplier har f.eks. ‘recalc’ kode i 3 forskellige klasser.
Hvorfor er der en forkert værdi i mit felt? Tja, først
skal jeg finde den rigtige klasse …
• Koden bliver nemt redundant – hvis f.eks.
International og Lead har brug for adresse validering?
• Hvad hvis et firma både er Leverandør og Kunde?
• Mon andre har haft samme problem? Kan der findes
et gennemtestet design pattern der løser problemet?
Company
+ create
+ delete
+ recalc
+ isValid
+ addStrategy( IStrategy)
AddressStrategy
+ create
+ delete
+ recalc
+ isValid
Private
International
Local
ExternalDataStrategy
+ create
+ delete
+ recalc
+ isValid
Ribers
LeadStrategy
+ create
+ delete
+ recalc
+ isValid Hot
Weak
C5
Strategy
En Company Class
◦ Flere forskellige Strategies kan tilføjes
◦ Nye Company objekter kan med fordel oprettes med en CompanyFactory
◦ createInternationalLead, createLocalSupplier, createCustomer, …
Tilsvarende pattern: Template Method
◦ Template Method er Compile-Time (inheritance)
◦ Strategy: Run-Time (composition) (artikel: link)
Eksempel: en.wikipedia.org/wiki/Strategy_pattern
Lær mere
Sourcemaking.com
◦ Bog (pdf) og videoer
◦ Patterns, UML og refactoring
◦ Det meste er gratis – hele pakken med video/bøger koster ca. $80
Head First Design Patterns
◦ Nem at læse
Jakob Majkilde: lotusscript.dk | xpages.dk | notesnet.dk/majkilde

Design patterns: Singleton & Strategy

  • 1.
    Design Patterns SINGLETON OGSTRATEGY Jakob Majkilde: lotusscript.dk | xpages.dk | notesnet.dk/majkilde
  • 2.
    Patterns – hvorfornu det? Genbrug andre erfaringer Bedre struktur – og genkendelig struktur Ingen grund til at opfinde tallerkenen igen
  • 3.
    Patterns til dethele Create ◦ Factory, Builder, Object Pool, Prototype, Singleton Structure ◦ Adapter, Bridge, Composite, Decorator, Facade, Flyweigth, Private Class Data, Proxy Behavior ◦ Chain of responbility, Command, Interpretor, Iterator, Mediator, Memento, Null Object, Observer, State, Strategy, Template method, Visitor
  • 4.
    Demonstration Hvordan får du2 knapper til at dele samme kode/variable på en Notes form? Og hvordan vil du gøre hvis de sidder på hver sin SubForm?
  • 5.
    Singleton Sikre at derkun er én instance af klassen (ét object) Regel #1: Vi bruger aldrig globale variable! ◦ Der er dog én undtagelse i Lotus Script: Execute Har selv brugt det til bl.a. ◦ getWorkflow ◦ getAttachmate ◦ getLog Sub Initialize getLog().print( "Hello" ) dim f as New Foo() call f.run() End Sub Class Foo Sub run() getLog().print( "Running..." ) End SUb End Class
  • 6.
    Lotus Script Singleton Uansetom getFoo() kaldes fra en knap, en subform eller PostOpen event, så returneres det samme object. Public function getFoo() As Foo Static fooSingleton As Foo If fooSingleton Is Nothing Then Set fooSingleton = New Foo() End If Set getFoo = fooSingleton End function
  • 7.
    Java Singleton Samme somi Lotus Script ◦ Bare lidt mere elegant ◦ Alt er samlet i én klasse ◦ Private constructor sikre mod forkert brug Thread safe / Unit Test? Google it: ◦ Stackoverflow.com/questions/6088195/ factory-for-thread-safe-singleton-in-java Serialization? Google it: ◦ javadata.blogspot.dk/2011/12/ singleton-and-serialization.html Factory pattern? ◦ Oplagt – men det bliver næste gang … public class Foo { private static Foo fooSingleton = new Foo(); private Foo() {} public static Singleton getInstance() { return fooSingleton; } }
  • 8.
    Demonstration Et CRM systemi Notes ◦ Klassisk response hierarki i Notes. ◦ Hoveddokumentet er ‘Company’ ◦ Kan være én af 2 typer: ‘Kunde’ el. ‘Emne’ ◦ Der er kun én Main Form. ◦ Der bruges hide/when til at styre forskellen mellem Kunde og Emne Back-end script ◦ Class: Company ◦ Recalc genberegner skjulte felter ◦ isValid checker om data er ok Hvorfor er det et dårligt design? Company Contact Document Company + create + delete + recalc + isValid • Der tilføjes nye firma typer: Leverandør, Entreprenør, Forhandler, Sama rbejdspartner, … • If…then…else konstruktion skal opdateres i både create, delete, recalc og isValid metoder • Koden bliver kompleks og uoverskuelig • Ændringer giver nemt følgefejl • Svært at teste og debugge
  • 9.
    Nyt design En klassetil hver firma type Hvorfor kan det være et dårligt design? Company + create + delete + recalc + isValid Customer + create + delete + recalc + isValid Supplier + create + delete + recalc + isValid Lead + create + delete + recalc + isValid XXX + create + delete + recalc + isValid Local + create + delete + recalc + isValid International + create + delete + recalc + isValid • Koden bliver hurtigt ‘fragmenteret’ – en local supplier har f.eks. ‘recalc’ kode i 3 forskellige klasser. Hvorfor er der en forkert værdi i mit felt? Tja, først skal jeg finde den rigtige klasse … • Koden bliver nemt redundant – hvis f.eks. International og Lead har brug for adresse validering? • Hvad hvis et firma både er Leverandør og Kunde? • Mon andre har haft samme problem? Kan der findes et gennemtestet design pattern der løser problemet?
  • 10.
    Company + create + delete +recalc + isValid + addStrategy( IStrategy) AddressStrategy + create + delete + recalc + isValid Private International Local ExternalDataStrategy + create + delete + recalc + isValid Ribers LeadStrategy + create + delete + recalc + isValid Hot Weak C5 Strategy En Company Class ◦ Flere forskellige Strategies kan tilføjes ◦ Nye Company objekter kan med fordel oprettes med en CompanyFactory ◦ createInternationalLead, createLocalSupplier, createCustomer, … Tilsvarende pattern: Template Method ◦ Template Method er Compile-Time (inheritance) ◦ Strategy: Run-Time (composition) (artikel: link) Eksempel: en.wikipedia.org/wiki/Strategy_pattern
  • 11.
    Lær mere Sourcemaking.com ◦ Bog(pdf) og videoer ◦ Patterns, UML og refactoring ◦ Det meste er gratis – hele pakken med video/bøger koster ca. $80 Head First Design Patterns ◦ Nem at læse Jakob Majkilde: lotusscript.dk | xpages.dk | notesnet.dk/majkilde