TDDB84: Lecture 5
Singleton, Builder, Proxy, Mediator
fredag 27 september 13
TDDB84: Lecture 5 Singleton, Builder, Proxy, Mediator fredag 27 - - PowerPoint PPT Presentation
TDDB84: Lecture 5 Singleton, Builder, Proxy, Mediator fredag 27 september 13 Creational Singleton Abstract Factory Builder Structural Bridge Composite Proxy Adapter Template method Behavioral Iterator Chain of responsibility
Singleton, Builder, Proxy, Mediator
fredag 27 september 13
Template method Iterator
Abstract Factory Composite Builder Singleton Proxy Mediator Adapter Bridge Observer Chain of responsibility
Observer
Creational patterns
Structural patterns
fredag 27 september 13
Template method Iterator
Abstract Factory Composite Builder Singleton Proxy Mediator Adapter Bridge Observer Chain of responsibility
Observer
Creational patterns
Structural patterns Dynamic proxies in C# & Java Classes ARE objects, and each object can have a class (in Ruby)
fredag 27 september 13
fredag 27 september 13
Let me go!
fredag 27 september 13
Let me go!
fredag 27 september 13
fredag 27 september 13
X1 Y1 Y2 f() y X y.g() g() Y
fredag 27 september 13
fredag 27 september 13
fredag 27 september 13
Context1 ConcreteStrategy1 ConcreteStrategy2 f() strategy Context strategy.g() g() Strategy
fredag 27 september 13
Arrays.sort(ducks, (arg0, arg1) -> new Integer(arg1.weight).compareTo(arg0.weight))
fredag 27 september 13
1. What are the relationships between the Strategy and Flyweight patterns? a) They both concern decoupling objects from their dependencies b) Using a Flyweight pattern may also require the Strategy pattern c) Using the Strategy pattern may also result in using the Flyweight pattern d) The Strategy pattern, if implemented with the use of type template parameters, does not necessitate the Flyweight pattern e) You often implement the Flyweight pattern by using the Strategy pattern for object creation f) The Flyweight pattern is a simplified form of the Strategy pattern
fredag 27 september 13
a) They both concern decoupling objects from their dependencies
dependencies. b) Using a Flyweight pattern may also require the Strategy pattern False. c) Using the Strategy pattern may also result in using the Flyweight pattern
d) The Strategy pattern, if implemented with the use of type template parameters, does not necessitate the Flyweight pattern
e) You often implement the Flyweight pattern by using the Strategy pattern for object creation
f) The Flyweight pattern is a simplified form of the Strategy pattern
the goal of flyweight pattern is to create new object, if they weren't created before,or to share object if the same object was created before.
fredag 27 september 13
Correct answers marked
a) They both concern decoupling objects from their dependencies
dependencies. b) Using a Flyweight pattern may also require the Strategy pattern False. c) Using the Strategy pattern may also result in using the Flyweight pattern
d) The Strategy pattern, if implemented with the use of type template parameters, does not necessitate the Flyweight pattern
e) You often implement the Flyweight pattern by using the Strategy pattern for object creation
f) The Flyweight pattern is a simplified form of the Strategy pattern
the goal of flyweight pattern is to create new object, if they weren't created before,or to share object if the same object was created before.
fredag 27 september 13
Correct answers marked
c) Using the Strategy pattern may also result in using the Flyweight pattern Flyweights are light-weight objects with externalized state, useful if supplying multiple strategies to a problem-solving context d) The Strategy pattern, if implemented with the use of type template parameters, does not necessitate the Flyweight pattern Using a template parameter, See C# demo
public class TaxCalculation<T>
fredag 27 september 13
c) Using the Strategy pattern may also result in using the Flyweight pattern Flyweights are light-weight objects with externalized state, useful if supplying multiple strategies to a problem-solving context d) The Strategy pattern, if implemented with the use of type template parameters, does not necessitate the Flyweight pattern Using a template parameter, See C# demo
public class TaxCalculation<T>
fredag 27 september 13
fredag 27 september 13
public class Singleton { private static Singleton instance = new Singleton(); private String name; public String getName() { return name; } private Singleton() { [ ... ] } }
fredag 27 september 13
public class Singleton { private static Singleton instance = new Singleton(); private String name; public String getName() { return name; } private Singleton() { [ ... ] } } private Singleton() { try { // Very expensive job indeed Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } name = Math.random() > 0.5 ? "Jonas" : "Anders"; }
fredag 27 september 13
public class Singleton { private static Singleton instance = new Singleton(); private String name; public String getName() { return name; } private Singleton() { [ ... ] } }
private Singleton() { try { // Very expensive job indeed Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } name = Math.random() > 0.5 ? "Jonas" : "Anders"; }
fredag 27 september 13
public class Singleton { private static Singleton instance = new Singleton(); private String name; public String getName() { return name; } private Singleton() { [ ... ] } }
public static void someOtherMethod(){ System.out.println("Hi there!"); }
private Singleton() { try { // Very expensive job indeed Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } name = Math.random() > 0.5 ? "Jonas" : "Anders"; }
fredag 27 september 13
Thread t1 = new Thread(new StaticMethodInvocation()); Thread t2 = new Thread(new SingletonLookup()); t0 = System.nanoTime(); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } someOtherMethod invoked Singleton name: Anders Singleton lookup took 1 003 348 000 ns Static method invocation took 1 002 463 000 ns
fredag 27 september 13
private static Singleton instance; public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
someOtherMethod invoked Static method invocation took 899 000 ns Singleton name: Anders Singleton lookup took 1 002 277 000 ns
fredag 27 september 13
fredag 27 september 13
private Singleton() { try { // Very expensive job indeed Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } name = Math.random() > 0.5 ? "Jonas" : "Anders"; }
fredag 27 september 13
private Singleton() { try { // Very expensive job indeed Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } name = Math.random() > 0.5 ? "Jonas" : "Anders"; } private static final class SingletonLookup implements Runnable { @Override public void run() { System.out.println(MessageFormat.format("Singleton name: {0}", Singleton.getInstance().getName())); } } public static void main(String[] args) { Thread t1 = new Thread(new SingletonLookup()); Thread t2 = new Thread(new SingletonLookup()); t0 = System.nanoTime(); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Singleton name after our threads have run: "+Singleton.getInstance().getName()); }
fredag 27 september 13
private Singleton() { try { // Very expensive job indeed Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } name = Math.random() > 0.5 ? "Jonas" : "Anders"; } private static final class SingletonLookup implements Runnable { @Override public void run() { System.out.println(MessageFormat.format("Singleton name: {0}", Singleton.getInstance().getName())); } } public static void main(String[] args) { Thread t1 = new Thread(new SingletonLookup()); Thread t2 = new Thread(new SingletonLookup()); t0 = System.nanoTime(); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Singleton name after our threads have run: "+Singleton.getInstance().getName()); }
fredag 27 september 13
private Singleton() { try { // Very expensive job indeed Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } name = Math.random() > 0.5 ? "Jonas" : "Anders"; } private static final class SingletonLookup implements Runnable { @Override public void run() { System.out.println(MessageFormat.format("Singleton name: {0}", Singleton.getInstance().getName())); } } public static void main(String[] args) { Thread t1 = new Thread(new SingletonLookup()); Thread t2 = new Thread(new SingletonLookup()); t0 = System.nanoTime(); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Singleton name after our threads have run: "+Singleton.getInstance().getName()); }
fredag 27 september 13
private Singleton() { try { // Very expensive job indeed Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } name = Math.random() > 0.5 ? "Jonas" : "Anders"; } private static final class SingletonLookup implements Runnable { @Override public void run() { System.out.println(MessageFormat.format("Singleton name: {0}", Singleton.getInstance().getName())); } } public static void main(String[] args) { Thread t1 = new Thread(new SingletonLookup()); Thread t2 = new Thread(new SingletonLookup()); t0 = System.nanoTime(); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Singleton name after our threads have run: "+Singleton.getInstance().getName()); }
fredag 27 september 13
private Singleton() { try { // Very expensive job indeed Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } name = Math.random() > 0.5 ? "Jonas" : "Anders"; } private static final class SingletonLookup implements Runnable { @Override public void run() { System.out.println(MessageFormat.format("Singleton name: {0}", Singleton.getInstance().getName())); } } public static void main(String[] args) { Thread t1 = new Thread(new SingletonLookup()); Thread t2 = new Thread(new SingletonLookup()); t0 = System.nanoTime(); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Singleton name after our threads have run: "+Singleton.getInstance().getName()); } Singleton name: Anders Singleton name: Jonas Singleton name after our threads have run: Anders
fredag 27 september 13
Singleton name: Anders Singleton name: Anders Singleton lookup took 1 003 340 000 ns Singleton lookup took 1 003 286 000 ns Singleton name after our threads have run: Anders public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
fredag 27 september 13
Singleton name: Anders Singleton name: Anders Singleton lookup took 1 003 340 000 ns Singleton lookup took 1 003 286 000 ns Singleton name after our threads have run: Anders public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
fredag 27 september 13
public enum EnumSingleton { INSTANCE; private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
fredag 27 september 13
Class MetaClass A A Object foo
class A; end foo = A.new class A; end
fredag 27 september 13
Class MetaClass A A Object foo Singleton Class for foo
class << foo; end class A; end foo = A.new class A; end
fredag 27 september 13
Class MetaClass A A Object foo Singleton Class for foo
class << foo; end class A; end foo = A.new class A; end
Singleton Class for A
class << A; end
fredag 27 september 13
class A end a = A.new class << A def new raise "Illegal!" end end
irb(main):014:0> a #<A:0x007f8d6b92bcb0> irb(main):016:0> A.new RuntimeError: Illegal! from (irb):10:in `new' from (irb):16 from /Users/olale/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>'
fredag 27 september 13
fredag 27 september 13
class
fredag 27 september 13
principles!
class
fredag 27 september 13
modification
classes
fredag 27 september 13
modification
classes
fredag 27 september 13
modification
classes
fredag 27 september 13
modification
classes
fredag 27 september 13
fredag 27 september 13
fredag 27 september 13
Client Director Builder build() buildA() buildB() buildC() getProduct()
fredag 27 september 13
fredag 27 september 13
fredag 27 september 13
fredag 27 september 13
fredag 27 september 13
fredag 27 september 13
fredag 27 september 13
Client requests a product from Factory Client receives a Factory Client receives an abstract product
fredag 27 september 13
Client requests a product from Factory Client receives a Factory Client receives an abstract product
Client asks Director to build Client receives a builder-specific product Client initializes Director with Builder Client requests product from Builder
fredag 27 september 13
Client requests a product from Factory Client receives a Factory Client receives an abstract product
Client asks Director to build Client receives a builder-specific product Client initializes Director with Builder Client requests product from Builder
fredag 27 september 13
Client requests a product from Factory Client receives a Factory Client receives an abstract product
Client asks Director to build Client receives a builder-specific product Client initializes Director with Builder Client requests product from Builder
fredag 27 september 13
Client requests a product from Factory Client receives a Factory Client receives an abstract product
Client asks Director to build Client receives a builder-specific product Client initializes Director with Builder Client requests product from Builder
fredag 27 september 13
Client requests a product from Factory Client receives a Factory Client receives an abstract product
Client asks Director to build Client receives a builder-specific product Client initializes Director with Builder Client requests product from Builder
fredag 27 september 13
fredag 27 september 13
fredag 27 september 13
products using the same Director
fredag 27 september 13
common interface for products
products using the same Director
fredag 27 september 13
common interface for products
to initialize builders and retrieve products
products using the same Director
fredag 27 september 13
modification
classes
fredag 27 september 13
fredag 27 september 13
checkCalendar(); checkSprinkler(); startCoffee(); //do more stuff }
checkDayOfTheWeek(); doShower(); doCoffee(); doAlarm(); //do more stuff }
checkCalendar(); checkAlarm(); //do more stuff }
checkCalendar(); checkShower(); checkTemperature //do more stuff }
fredag 27 september 13
if(alarmEvent)(){ checkCalendar(); checkShower(); checkTemp(); //do more stuff } if(weekend){ checkWeather(); } if(trashDay){ resetAlarm(); }
fredag 27 september 13
fredag 27 september 13
fredag 27 september 13
fredag 27 september 13
single point of failure
fredag 27 september 13
single point of failure
colleagues can be varied independently
fredag 27 september 13
single point of failure
colleagues can be varied independently
relationships with 1-M relationships with the Mediator in the middle
fredag 27 september 13
single point of failure
colleagues can be varied independently
relationships with 1-M relationships with the Mediator in the middle
management
fredag 27 september 13
fredag 27 september 13
fredag 27 september 13
Id Name Age 1 Ola 34 2 Lisa 31 Id StartDate EndDate PersonId 2012-05-01 1 2012-06-01 1 2 2001-04-06 2006-07-29 2 3 2004-01-01 2010-12-31 1 4 2006-07-30 2007-11-30 2
fredag 27 september 13
and map them to objects Intercept method calls to access the property Employments (get_Employments) and fetch the related Employments records for the current Person object
people.First ().Employments.Should ().NotBeNull ();
fredag 27 september 13
public class LazyLoadingInterceptor<T>:BaseInterceptor,IInterceptor where T:class, new() { private static string GetPropertyName(string getterName) { return getterName.Remove(0,4); } public void Intercept(IInvocation invocation) {
// Get the target property access method var target=invocation.MethodInvocationTarget; string propertyName=GetPropertyName(target.Name); if(target.Name.StartsWith("get_")) { Prefetcher<T>.FetchRelatedProperty(new List<T>() { proxy as T },typeof(T).GetProperty(propertyName)); } invocation.Proceed(); } }
fredag 27 september 13
fredag 27 september 13
return (PersonBean) Proxy.newProxyInstance( person.getClass().getClassLoader(), person.getClass().getInterfaces(), new NonOwnerInvocationHandler(person)); package headfirst.proxy.javaproxy;
fredag 27 september 13
class A def initialize name @name=name end def foo "foo" end def bar "bar" end def to_s @name end end class AProxy def initialize(a) @a = a end def method_missing(m,*args) p "calling #{m} on #{@a}" @a.send(m,*args) end end
fredag 27 september 13
class A def initialize name @name=name end def foo "foo" end def bar "bar" end def to_s @name end end class AProxy def initialize(a) @a = a end def method_missing(m,*args) p "calling #{m} on #{@a}" @a.send(m,*args) end end irb(main):067:0> proxy=AProxy.new(A.new("original_object")) #<AProxy:0x007fa26a12bc40 @a=#<A:0x007fa26a12bc68 @name="original_object">> irb(main):068:0> proxy.foo "calling foo on original_object" "foo"
fredag 27 september 13
fredag 27 september 13
implementation, proxies may incur an overhead cost for method calls
fredag 27 september 13
implementation, proxies may incur an overhead cost for method calls
implementation, proxies may require that all proxied objects implement interfaces (in Java)
fredag 27 september 13
implementation, proxies may incur an overhead cost for method calls
implementation, proxies may require that all proxied objects implement interfaces (in Java)
to be referenced before they are fully initialized
fredag 27 september 13
implementation, proxies may incur an overhead cost for method calls
implementation, proxies may require that all proxied objects implement interfaces (in Java)
to be referenced before they are fully initialized
such as access control, logging, method call forwarding, lazy loading
fredag 27 september 13
Summary
fredag 27 september 13
fredag 27 september 13