Lecture 05 Builder, Singleton, Proxy Peter Bunus Dept of Computer and Information Science Linköping University, Sweden petbu@ida.liu.se
The Constitution of Software Architects Encapsulate what varies. Program to an interface not to an implementation. Favor Composition over Inheritance. Classes should be open extension but closed for modification Don t call us, we ll call you A Class should have only one reason to change Depend upon abstractions. Do not depend upon concrete classes.?????????????????? Peter Bunus 2
The Builder Pattern Peter Bunus 3
The Builder - Intent Separate the construction of a complex object from its representation so that the same construction process can create different representations. A client uses the builder pattern like an individual would use an interior designer and furniture maker to build furniture - the individual (Client) tells the designer what he wants, and the designer (Director), the furniture maker (Builder), and his tool (Concrete builders) create the furniture (Product) Peter Bunus 4
Builder - Example 1) The boss tells Joe what he wants Director Builder 3) Joe tells the furniture maker to build a chair. Note that the furniture maker could have also built a beach furniture or a skateboard. 1) The boss wants some new furniture. He calls his direct aid. Concrete Builder1 Concrete Builder2 Concrete Builder1 Client Product 3) The boss gets the armchair produced by the furniture maker and his tools Peter Bunus 5
Why Use Builder? Use the builder pattern when: The algorithm for creating a complex object should be independent of the parts that make up the object and how they are assembled The construction process must allow different representations for the object that s constructed Builder is very useful because it allows the program to create a flexible number of objects you can add or delete objects as necessary Peter Bunus 6
Builder Non Software Example Peter Bunus 7
The Builder Design Pattern Separate the construction of a complex object from its representation so that the same construction process can create different representations. The client creates the Director object and configures it with the desired Builder object. Director notifies the builder whenever a part of the product should be built. Builder handles requests from the director and adds parts to the product. The client retrieves the product from the builder. Peter Bunus 8
Builder - Example Peter Bunus 9
Consequences of the Builder Pattern A Builder lets you vary the internal representation of the product it builds. It also hides the details of how the product is assembled. Each specific builder is independent of the others and of the rest of the program. This improves modularity and makes the addition of other builders relatively simple. Because each builder constructs the final product step-by-step, depending on the data, you have more control over each final product that a Builder constructs. A Builder pattern is somewhat like an Abstract Factory pattern in that both return classes made up of a number of methods and objects. The main difference is that while the Abstract Factory returns a family of related classes, the Builder constructs a complex object step by step depending on the data presented to it. Peter Bunus 10
Builder vs. Abstract Factory Return classes made up of a number of methods and objects Builder constructs a complex object step by step depending on the data presented to it. Return classes made up of a number of methods and objects Builder Abstract Factory returns a family of related classes Abstract Factory Peter Bunus 11
The Singleton Pattern Peter Bunus 12
A Java Programming Exercise How you would create a Duck object? new MyDuck What if somebody else would like to create a Duck object as well? Could she/he call the new on MyDuck again? Yes, why not An how about now? private MyDuck{ Well, only classes in the same package can instantiate it Peter Bunus 13
A Java Programming Exercise Did you know you could do this? public MyDuck{ private MyDuck(){ You can t instantiate this class because it has a private constructor Wait a minute... MyDuck can call its private contsructor. But I need to have an instance to call it Ok, What does this mean? public MyDuck{ public static MyDuck getinstance(){ MyDuck.getInstance() Wonderfull getinstance() is a static method. One uses the class name to reference a static method Peter Bunus 14
A Java Programming Exercise public MyDuck{ private MyDuck(){ public MyDuck{ public static MyDuck getinstance(){ public MyDuck{ private MyDuck(){ public static MyDuck getinstance(){ return new MyDuck(); How you would create a Duck object now? MyDuck.getInstance() Peter Bunus 15
A Java Programming Exercise Can you create now more than one Ducks? public MyDuck{ private MyDuck(){ public static MyDuck getinstance(){ Yes, why not return new MyDuck(); public MyDuck{ But I Would like to have only one Duck private static MyDuck oneduck; How you do it? private MyDuck(){ public static MyDuck getinstance(){ if (oneduck == null){ oneduck = new MyDuck(); return oneduck; Peter Bunus 16
A C++ Programming Exercise class MyDuck{ public: static MyDuck* getinstance(); protected: MyDuck(); private: static MyDuck * oneduck; MyDuck* MyDuck::oneDuck = 0; MyDuck * MyDuck ::getinstance () { if (oneduck == 0) { oneduck = new MyDuck; return oneduck; Peter Bunus 17
Election Day public class PrimeMinister{ private boolean speech; private boolean cabinet; public PrimeMinister(){ speech = false; cabinet = true; public void writespeech(){ // write the speech here speech = true public void deliverspeech(){ if (speech==true){ //deliver speech for the parlament speech = false; public void formcabinet(){ if (cabinet == true){ //form the governement cabinet cabinet = false Peter Bunus 18
Help the Electors Could you make sure that only one Prime minister is elected by turning our class into a singleton public class PrimeMinister{ private boolean speech; private boolean cabinet; private static PrimeMinister uniquepm private public PrimeMinister(){ speech = false; cabinet = true; public void writespeech(){ // write the speech here speech = true public void deliverspeech(){ if (speech==true){ //deliver speech for the parlament speech = false; public static PrimeMinister getelected(){ if(uniquepm == null){ uniquepm = new PrimeMinister(); return uniquepm; Peter Bunus 19
The Election on Java Island Went Wrong Mayday, Mayday. We just finished our multithreaded election and now there are two guys delivering speeches and forming a government. What happened? You were suppose to deliver me a singleton class. PrimeMinister pm = PrimeMinister.getElected(); formcabinet(); writespeech(); deliverspeech(); Peter Bunus 20
What happened? Thread 1 Thread 2 Value of uniquepm public static PrimeMinister getelected(){ public static PrimeMinister getelected(){ if (uniquepm == null){ if (uniquepm == null){ uniquepm = new PrimeMinister() return = uniquepm; uniquepm = new PrimeMinister() return = uniquepm; Peter Bunus 21
Syncronizing the Multithreaded Elections public static syncronized PrimeMinister getelected(){ if(uniquepm == null){ uniquepm = new PrimeMinister(); return uniquepm; public static PrimeMinister getelected(){ Thread 1 Thread 2 By adding the syncronized keyword to getelected() we force every thread to wait its turn before it can enter the method. This is no two thread may enter the method at the same time Value of uniquepm if (uniquepm == null){ uniquepm = new PrimeMinister( ) return = uniquepm; public static PrimeMinister getelected(){ if (uniquepm == null){ uniquepm = new PrimeMinister( ) return = uniquepm; Peter Bunus 22
Singleton Non Software Example Peter Bunus 23
The Singleton Pattern Ensure a class only has one instance, and provide a global point of access to it. Peter Bunus 24
Summary of Creational Patterns The Factory Pattern is used to choose and return an instance of a class from a number of similar classes based on data you provide to the factory. The Abstract Factory Pattern is used to return one of several groups of classes. In some cases it actually returns a Factory for that group of classes. The Builder Pattern assembles a number of objects to make a new object, based on the data with which it is presented. Frequently, the choice of which way the objects are assembled is achieved using a Factory. The Singleton Pattern is a pattern that insures there is one and only one instance of an object, and that it is possible to obtain global access to that one instance. Peter Bunus 25
The Proxy Pattern Peter Bunus 26
The Proxy Pattern (prok-se) An agent or substitute authorized to act for another What is expensive? Object Creation Object Initialization Defer object creation and object initialization to the time you need the object Proxy pattern: Reduces the cost of accessing objects Uses another object ( the proxy ) that acts as a stand-in for the real object The proxy creates the real object only if the user asks for it Peter Bunus 27
Proxy - Example Peter Bunus 28
Proxy Example Peter Bunus 29
Proxy Non Software Example Peter Bunus 30
The Proxy Pattern Here's a possible object diagram of a proxy structure at run-time: Peter Bunus 31
The Proxy Pattern - Example Peter Bunus 32
A Proxy Image Example We would like to create a simple program to display an image on a JPanel when it is loaded. Rather than loading the image directly, we use a class we call ImageProxy to defer loading and draw a rectangle around the image area until loading is completed. Peter Bunus 33
A Proxy Image Example public class ProxyDisplay extends JxFrame { public ProxyDisplay() { super("display proxied image"); JPanel p = new JPanel(); getcontentpane().add(p); p.setlayout(new BorderLayout()); ImageProxy image = new ImageProxy("elliott.jpg", 321, 271); p.add("center", image); p.add("north", new Label(" ")); p.add("west", new Label(" ")); setsize(370, 350); setvisible(true); //------------------------------------ static public void main(string[] argv) { new ProxyDisplay(); Peter Bunus 34
A Proxy Image Example public ImageProxy(String filename, int w, int h) { height = h; width = w; tracker = new MediaTracker(this); img = Toolkit.getDefaultToolkit().getImage(filename); tracker.addimage(img, 0); //watch for image loading imagecheck = new Thread(this); imagecheck.start(); //start 2nd thread monitor //this begins actual image loading try{ tracker.waitforid(0,1); catch(interruptedexception e){ Peter Bunus 35
A Proxy Image Example public void run() { //this thread monitors image loading //and repaints when done //the 1000 msec is artifically long //to allow demo to display with delay try{ Thread.sleep(1000); while(! tracker.checkid(0)) Thread.sleep(1000); catch(exception e){ repaint(); Peter Bunus 36
A Proxy Image Example public void paint(graphics g) { if (tracker.checkid(0)) { height = img.getheight(frame); //get height width = img.getwidth(frame); //and width g.setcolor(color.lightgray); //erase box g.fillrect(0,0, width, height); g.drawimage(img, 0, 0, this); //draw loaded image else { //draw box outlining image if not loaded yet g.setcolor(color.black); g.drawrect(1, 1, width-2, height-2); Peter Bunus 37