1 Java Design Patterns Java Design Patterns Layered

  • Slides: 35
Download presentation
1 Java Design Patterns

1 Java Design Patterns

Java Design Patterns • • Layered Initialization Dynamic Linkage Cache Management Null Object All

Java Design Patterns • • Layered Initialization Dynamic Linkage Cache Management Null Object All these patterns are from: “Patterns In Java(TM)” by Mark Grand 2

Layered Initialization • Synopsis > • Allow creation of specialized subclasses using a common

Layered Initialization • Synopsis > • Allow creation of specialized subclasses using a common set of logic. Context > > You have a piece of logic that requires partial execution prior to determining which subclass methods might be used. ° You need to layer the initializations of the objects to process the complex logic or complex data. Sometimes, a specific subclass should be created to accomplish a task. ° However, the information “which sub-class to create? ” can’t be computed at compile time (see java. net. URL class). • Like if you support multiple databases in the back-end, you can’t initialize all of them and you can’t know which until runtime. 3

Layered Initialization (cont’) • Forces ° A specialized class must be chosen to process

Layered Initialization (cont’) • Forces ° A specialized class must be chosen to process complex data ° The logic to choose a specialized class should be encapsulated so that it is transparent to the classes that provide data for an instance of the specialized class to process. ° The constructors of the specialized classes and their superclasses are invoked after it has been decided which specialized class to instantiate. This means that the constructors can’t participate in the decision of which class to instantiate. ° To maintain low coupling, only one of the objects that participate in the layered initialization pattern should be visible to the object that provides the complex data ° Putting the decision of which class to instantiate into a separate class reduces the effort required to maintain the other classes. If a database migrates to a different type of engine or a new class becomes available that provides better access to it, then the corresponding change in the program is limited to the class that decides what class to instantiate. 4

Layered Initialization (cont’) • Structure Requests-creation <<interface>> Service. Impl. Factory. IF Data. Query set.

Layered Initialization (cont’) • Structure Requests-creation <<interface>> Service. Impl. Factory. IF Data. Query set. Factory(: Service. Impl. Factory. IF) create. Service. Impl Uses Service. Impl. Factory. IF <<interface>> Service. Impl. IF create. Service. Impl * Creates Service. Impl 1 5

Layered Initialization (cont’) • Participants > > > Service ° Only objects that participate

Layered Initialization (cont’) • Participants > > > Service ° Only objects that participate that are visible to objects outside the pattern. ° Encapsulate logic common to all specialized cases. Delegates specialized operations and specialized portions of common operations to classes that implement Service. Impl. IF interface. Service. Imple. IF ° Service objects access Service. Impl objects using this interface. Service. Impl. Factory. IF ° Service object uses this interface to access a Service. Impl. Factory object. Service. Impl. Factory ° Creates Service. Impl objects. ° Implements Service. Impl. Factory. IF. Service. Impl 1, Service. Impl 2, … ° Implement Service. Impl. IF. ° Provide specialized logic needed by service class methods. 6

Layered Initialization (cont’) • Consequences > • Advantages: ° The complexity of initializing an

Layered Initialization (cont’) • Consequences > • Advantages: ° The complexity of initializing an object using data that requires analysis before the initialization can proceed is hidden from client objects. ° The clients of the service class have no dependencies on the objects that participate in the layered initialization pattern, except the service object. Implementation > > Make only the Service class visible ° encapsulate all pattern-related classes in a package and make only the Service class and Service. Impl. Factory. IF interface public. Setting the factory ° In most cases, the factory will be set at some initialization phase. If you know that setting the factory more than once is an error a more robust implementation will be to report an error (e. g. by throwing an exception) if this happens. 7

Layered Initialization (cont’) • Java API usage > class java. net. URL ° a

Layered Initialization (cont’) • Java API usage > class java. net. URL ° a URL might be: • http: //www. cnn. com • mailto: cs 236700@cs. technion. ac. il • Code Example > consider the Data. Query example: public class Data. Query { private Data. Query. Factory. IF factory; public set. Factory(Data. Query. Factory. IF factory) { … } public Data. Query(String query) { … String db. Name = null; Data. Query. Impl. IF dq dq = (Data. Query. Impl. IF)factory. create. Data. Query. Impl(db. Name); … } } 8

Layered Initialization (cont’) • Code Example (cont’) public interface Data. Query. Factory. IF {

Layered Initialization (cont’) • Code Example (cont’) public interface Data. Query. Factory. IF { } class My. Data. Factory implements Data. Query. Factory. IF { private static Hashtable classes = new Hashtable(); static { classes. put(“INVENTORY”, data. Query. Oracle. Query. class); classes. put(“INVENTORY”, data. Query. My. SQLQuery. class); classes. put(“INVENTORY”, data. Query. DB 2 Query. class); … } public Data. Query. Factory. IF create. Data. Query. Impl(String db. Name) { Class clazz = (Class)classes. get(db. Name); try { return (Data. Query. Factory. IF)clazz. new. Instance(); } catch (Exception e) { return null; } } } 9

Layered Initialization (cont’) • Related Patterns > > > Builder ° uses layered initialization

Layered Initialization (cont’) • Related Patterns > > > Builder ° uses layered initialization to create specialized objects. Delegation ° Service class delegates specialized operations to objects that implement Service. Impl interface. Facade ° layered initialization is a facade in the sense that it hides all other objects that participate in the pattern from clients of service objects. Factory Method ° when the choice of which kind of object to create doesn’t involve any significant preprocessing of data, the Factory Method pattern may be more appropriate. Composite ° when more than 2 layers are needed for initialization, you can combine with the Composite pattern to perform as many layers as needed. 10

Dynamic Linkage • Synopsis > • Allow a program, upon request, to load and

Dynamic Linkage • Synopsis > • Allow a program, upon request, to load and use arbitrary classes that implement a known interface. Context > > plugablility ° can use new classes at runtime. They only have to support a given interface. Extendability ° you may add new features (probably using composition of primitive features) to an existing application. 11

Dynamic Linkage (cont’) • Forces > > • A program must be able to

Dynamic Linkage (cont’) • Forces > > • A program must be able to load and use arbitrary classes that it has no prior knowledge of. An instance of a loaded class must be able to call back to the program that loaded it Structure Uses <<interface>> Environment. IF Abstract. Loadable. Class operation 1() operation 2() set. Environment(: Environment. IF) Uses Environment Concrete. Loadable. Class 12

Dynamic Linkage (cont’) • Participants > > Environment. IF ° an interface that declares

Dynamic Linkage (cont’) • Participants > > Environment. IF ° an interface that declares the methods provided by an environment object that a loaded class can call. Environment ° the part of the environment that loads a Concrete. Loadable. Class ° Implements Environment. IF ° a reference to an instance of this class is passed to instances of the Concrete. Loadable. Class class, so they can call the methods of the Environment declared by the Environment. IF. Abstract. Loadable. Class ° contains a method set. Environment that take an Environment. IF. ° contains a start method called by the Environment. Concrete. Loadable. Class ° subclass of Abstract. Loadable. Class. ° may be dynamically loaded. 13

Dynamic Linkage (cont’) • Consequences > > • Advantages: ° Subclasses of Abstract. Loadable.

Dynamic Linkage (cont’) • Consequences > > • Advantages: ° Subclasses of Abstract. Loadable. Class may be dynamically loaded. ° The operating environment and the loaded classes don’t need any specific foreknowledge of each other. Disadvantages: ° increase in the total amount of time it takes for a program to load all of the classes it uses. ° However, it does have the effect of spreading out over time. ° Presents a significant security risk (by running code you did not distribute) Implementation ° the Environment class must somehow know the name of the class that it wants to load ° problems may arise because of different versions of helper classes that might be needed ° Java. Beans offers another method, based on naming conventions and reflection classes. 14

Dynamic Linkage (cont’) • Java API usage > • 15 Java Applet class Code

Dynamic Linkage (cont’) • Java API usage > • 15 Java Applet class Code Example > consider the Food. Processor example: public interface Food. Processor. Environment. IF { public void slice(int width); public double weight(); … } public abstract class Abstract. Food. Processor. Program { private Food. Processor. Environment. IF environment; public void set. Environment(Food. Processor. Environment. IF environment) { this. environment = environment; } protected Food. Processor. Environment. IF get. Environment() { return environment; } public abstract String get. Name(); public abstract void start(); … }

Dynamic Linkage (cont’) • Code Example (cont’) public class Food. Processor. Environment implement Food.

Dynamic Linkage (cont’) • Code Example (cont’) public class Food. Processor. Environment implement Food. Processor. Environment. IF { private static final URL[] class. Path; static { try { class. Path = new URL{} {new URL(“file: ///bin”)}; } catch (java. net. Mailformed. URLException e) { throw new Exception. Intializer. Error(e); } } public void slice(int width) { … } public double weigh() { double weight = 0. 0; … return weight; } 16

Dynamic Linkage (cont’) • Code Example (cont’) void run(String program. Name) { URLClass. Loader

Dynamic Linkage (cont’) • Code Example (cont’) void run(String program. Name) { URLClass. Loader class. Loader = new URLClass. Loader(clas. Path); Class program. Class; try { program. Class = class. Loader. load. Class(program. Name); } catch (Class. Not. Found. Exception e) { … return; } Abstract. Food. Processor. Program program; try { program = (Abstract. Food. Processor. Program) program. Class. new. Instance(); } catch (Exception e) { … return; } program. set. Environment(this); display(program. get. Name()); program. start(); } } 17

Dynamic Linkage (cont’) • Code Example (cont’) public class Concrete. Food. Processor. Program extends

Dynamic Linkage (cont’) • Code Example (cont’) public class Concrete. Food. Processor. Program extends Abstract. Food. Processor. Program { public String get. Name() { return “Chocolate Milk”; } public void start() { double weight = get. Environment(). weigh(); if (weight > 120. 0 && weight < 160. 0) get. Environment(). mix(4); … } } 18

Dynamic Linkage (cont’) • Related Patterns > Virtual Proxy ° sometime uses Dynamic Linkage

Dynamic Linkage (cont’) • Related Patterns > Virtual Proxy ° sometime uses Dynamic Linkage to load the class it needs to create its underlying object. 19

Cache Management • Synopsis > • Context > • Implement a cache. re-creating can

Cache Management • Synopsis > • Context > • Implement a cache. re-creating can be a waste - reuse is good! ° why not keep objects that are re-created and avoid the overhead of memory de-allocation/allocation. Forces ° there is a need for access to objects that take a long time to construct ° the number of objects that are expensive to construct is small. If more objects are created then some objects will be discarded. ° An upper bound on the number of objects requires an enforcement policy to determine which objects will be stored in cache and which will be discarded after use. 20

21 Cache Management (cont’) • Structure Cache. Manager Cache-objects-for Cache add. Object(: Object) fetch.

21 Cache Management (cont’) • Structure Cache. Manager Cache-objects-for Cache add. Object(: Object) fetch. Object(: Object. Key) cacher Create-objects-for-caching Object. Key Caches fetcher Object. Creator create. Object(: Object. Key) Object

Cache Management (cont’) • Participants > > Object. Key ° identify the content of

Cache Management (cont’) • Participants > > Object. Key ° identify the content of an Object. Cache. Manager ° all requests for objects from classes that do not participate in the pattern are presented to the Cache. Manager. ° asks the cache for an object for a specific Object. Key. ° If there is no Object for Object. Key, asks the Object. Creator to create an appropriate instance. Object. Creator ° creates objects that are not in the Cache ° manages the collection of Objects. ° stores new Objects according to cache management policy. ° discards old objects according to cache management policy. 22

Cache Management (cont’) • Consequences > > • Advantages: ° transparent for users (assuming

Cache Management (cont’) • Consequences > > • Advantages: ° transparent for users (assuming they already know about factories). ° efficiency - spending less time on object creation. Disadvantages: ° outside sources might cause consistency problems. Implementation > > Some things need to be very quick ° finding objects given an Object. Key. ° search is more frequent from insert/remove so optimize for search… ° …however, there also frequent insert/remove actions so should also be reasonable a hashtable is a good collection class 23

Cache Management (cont’) • Code Example > consider the Employee Timekeeping example: public class

Cache Management (cont’) • Code Example > consider the Employee Timekeeping example: public class Employee. Profile. Manager { private Employee. Cache cache = new Employee. Cache(); private Employee. Profile. Fetcher server = new Employee. Profile. Fetcher(); Employee. Profile fetch. Employee(Employee. ID id) { Employee. Profile profile = cache. fetch. Employee(id); if (profile == null) { profile = server. fetch. Employee(id); if (profile != null) { cache. add. Employee(profile); } } return profile; } } 24

Cache Management (cont’) • Code Example (cont’) class Employee. Cache { private Hashtable cache

Cache Management (cont’) • Code Example (cont’) class Employee. Cache { private Hashtable cache = new Hashtable(); Linked. List mru = null; Linked. List lru = null; private final int MAX_CACHE_SIZE = 80; private int current. Cache. Size = 0; public Employee. Profile fetch. Employee(Employee. ID id) { Linked. List found. Link = (Linked. List)cach. get(id); if (found. Link == null) return null; if (mru != found. Link) { if (found. Link. previous != null) found. Link. previous. next = found. Link. next; if (found. Link. next != null) found. Link. next. previous = found. Link. previous; found. Link. previous = null; found. Link. next = mru; mru = found. Link; } return found. Link. profile; } 25

Cache Management (cont’) public void add. Employee(Employee. Profile emp) { Employee. ID id =

Cache Management (cont’) public void add. Employee(Employee. Profile emp) { Employee. ID id = emp. get. ID(); if (cache. get(id) == null) { if (current. Cache. Size == 0) { lru = mru = new Linkd. List(); mru. profile = emp; } else { Linked. List new. Link; if (current. Cache. Szie >= MAX_CACHE_SIZE) { new. Link = lru; lru = new. Link. previous; cache. remove(new. Link); lru. next = null; } else { new. Link = new Linked. List(); } new. Link. profile = emp; new. Link. next = mru; new. Link. previous = null; mru = new. Link; } cache. put(id, mru); current. Cache. Size++; } else { fetch. Employee(id); } } 26

Cache Management (cont’) • Code example (cont’) private class Linked. List { Employee. Profile

Cache Management (cont’) • Code example (cont’) private class Linked. List { Employee. Profile profile; Linked. List previous; } } class Employee. Profile { private Employee. ID id; privtae Locale locale; private boolean supervisor; private String name; public Employee. Profile(Employee. ID id, Locale locale, boolean supervisor, String name) { this. id = id; this. locale = locale; this. supervisor = supervisor; this. name = name; } public Employee. ID get. ID() { return id; } public Locale get. Locale() { return locale; } public boolean is. Supervisor() { return supervisor; } public String get. Name() { return name; } } 27

Cache Management (cont’) • Code example (cont’) class Employee. ID { private String id;

Cache Management (cont’) • Code example (cont’) class Employee. ID { private String id; public Employee. ID(String id) { this. id = id; } public int hash. Code() { return id. hash. Code(); } public boolean equals(Object obj) { return (obj instanceof Employee. ID && id. equals(((Employee. ID)obj). id) ); } public String to. String() { return id; } } 28

Cache Management (cont’) • Related Patterns > > > Facade ° the cache management

Cache Management (cont’) • Related Patterns > > > Facade ° the cache management pattern uses the facade pattern. Publish-Subscribe ° you can use the publish-subscribe pattern to ensure the read consistency of a cache. Remote Proxy ° provides an alternative to cache management by working with objects that exist in a remote environment. Template Method ° the cache management pattern uses the template method pattern to keep it’s cache class reusable across application domains. Virtual Proxy ° often used with a variant of the virtual proxy to make the cache transparent to objects that access objects in the cache. 29

Null Object • Synopsis > • Context > > • An alternative for using

Null Object • Synopsis > • Context > > • An alternative for using null to indicate the absence why test for null ° we may just ignore calls & implement a no-op iterators on tree-structures ° very useful technique Forces ° A class delegates an operation to another class. The delegating class does not usually care how the other class implements the operation. However, it sometimes does require that the operation be implemented by doing nothing. ° You want the class delegating the operation to delegate it in all cases, including the do-nothing case. You do not want the donothing case to require any special code in the delegating class. 30

31 Null Object (cont’) • Structure Delegator Uses Abstract. Operation Null. Operation • Participants

31 Null Object (cont’) • Structure Delegator Uses Abstract. Operation Null. Operation • Participants > > Delegator ° delegates operations to Abstract. Operation. ° doesn’t need to check for null. Abstract. Operation ° defines the interface for operation. Real. Opeation ° implements the operation Null. Operation ° implements the operation as a no-op Real. Operation

Null Object (cont’) • Consequences > > • Advantages: ° no need for special

Null Object (cont’) • Consequences > > • Advantages: ° no need for special handlers/checks for null ° do-nothing behavior is reusable Disadvantages: ° increases the number of classes in the program Implementation ° no state needed for null objects - consider implementing them as a singleton. 32

Null Object (cont’) • Code Example > consider the Warning. Router example: public interface

Null Object (cont’) • Code Example > consider the Warning. Router example: public interface Warning. Router { public boolean route. Warning(String msg); } class Business. Rule { private Warningrouter warning; private Date expiration. Date = new Date(Long. MAX_VALUE); … Business. Rule() { … if (new Date(). after(expiration. Date)) { String msg = get. Class(). get. Name() + “ has expired. ”; warning. route. Warning(msg); } … } } 33

Null Object (cont’) • Code Example (cont’) class Warning. Dialog implements Warning. Router {

Null Object (cont’) • Code Example (cont’) class Warning. Dialog implements Warning. Router { public boolean route. Warning(String warning) { int r; r = JOption. Pane. show. Confirm. Dialog(null, warning, “Warning”, JOption. Pane. OK_CANCEL_OPTION, JOption. Pane. WARNING_MESSAGE); return r == 0; } } class Ignore. Warning implements Warning. Router { public boolean route. Warning(String warning) { return true; } } 34

Null Object (cont’) • Related Patterns > > Singleton ° if instances of the

Null Object (cont’) • Related Patterns > > Singleton ° if instances of the Null. Operation class contain no instancespecific information, then you can save time and memory by implementing Null. Operation class as a singleton class. Strategy ° the Null Object pattern is often used with the Strategy pattern. 35