1 / 35

Layered Initialization in Java: Dynamic and Transparent Object Creation

This pattern allows specialized subclasses to be selectively created based on varying conditions at runtime. By encapsulating the logic to choose specialized classes, complex data or operations can be processed efficiently. The pattern maintains low coupling and easily accommodates changes in specialized classes without impacting the rest of the system.

lsloan
Download Presentation

Layered Initialization in Java: Dynamic and Transparent Object Creation

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. JavaDesign Patterns SD

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

  3. SD 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 run-time.

  4. SD 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.

  5. SD Structure Layered Initialization (cont’)‏ Requests-creation DataQuery <<interface>> ServiceImplFactoryIF setFactory(:ServiceImplFactoryIF)‏ createServiceImpl Uses ServiceImplFactoryIF <<interface>> ServiceImplIF createServiceImpl * Creates ServiceImpl1 ServiceImpl1

  6. SD 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 ServiceImplIF interface. ServiceImpleIF Service objects access ServiceImpl objects using this interface. ServiceImplFactoryIF Service object uses this interface to access a ServiceImplFactory object. ServiceImplFactory Creates ServiceImpl objects. Implements ServiceImplFactoryIF. ServiceImpl1, ServiceImpl2, … Implement ServiceImplIF. Provide specialized logic needed by service class methods.

  7. SD 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 ServiceImplFactoryIF 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.

  8. SD Layered Initialization (cont’)‏ Java API usage class java.net.URL a URL might be: http://www.cnn.com mailto:cs236700@cs.technion.ac.il Code Example consider the DataQuery example: public class DataQuery { private DataQueryFactoryIF factory; public setFactory(DataQueryFactoryIF factory) { … } public DataQuery(String query) { … String dbName = null; DataQueryImplIF dq dq = (DataQueryImplIF)factory.createDataQueryImpl(dbName); … } }

  9. SD Layered Initialization (cont’)‏ Code Example (cont’)‏ public interface DataQueryFactoryIF { } class MyDataFactory implements DataQueryFactoryIF { private static Hashtable classes = new Hashtable(); static { classes.put(“INVENTORY”,dataQuery.OracleQuery.class); classes.put(“INVENTORY”,dataQuery.MySQLQuery.class); classes.put(“INVENTORY”,dataQuery.DB2Query.class); … } public DataQueryFactoryIF createDataQueryImpl(String dbName) { Class clazz = (Class)classes.get(dbName); try { return (DataQueryFactoryIF)clazz.newInstance(); } catch (Exception e) { return null; } } }

  10. SD Layered Initialization (cont’)‏ • Related Patterns • Builder • uses layered initialization to create specialized objects. • Delegation • Service class delegates specialized operations to objects that implement ServiceImpl 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.

  11. SD 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.

  12. SD 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>> EnvironmentIF AbstractLoadableClass operation1()‏ operation2()‏ setEnvironment(:EnvironmentIF)‏ Uses Environment ConcreteLoadableClass

  13. SD Dynamic Linkage (cont’)‏ Participants EnvironmentIF 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 ConcreteLoadableClass Implements EnvironmentIF a reference to an instance of this class is passed to instances of the ConcreteLoadableClass class, so they can call the methods of the Environment declared by the EnvironmentIF. AbstractLoadableClass contains a method setEnvironment that take an EnvironmentIF. contains a start method called by the Environment. ConcreteLoadableClass subclass of AbstractLoadableClass. may be dynamically loaded.

  14. SD Dynamic Linkage (cont’)‏ Consequences Advantages: Subclasses of AbstractLoadableClass 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 JavaBeans offers another method, based on naming conventions and reflection classes.

  15. SD Dynamic Linkage (cont’)‏ Java API usage Java Applet class Code Example consider the FoodProcessor example: public interface FoodProcessorEnvironmentIF { public void slice(int width); public double weight(); … } public abstract class AbstractFoodProcessorProgram { private FoodProcessorEnvironmentIF environment; public void setEnvironment(FoodProcessorEnvironmentIF environment) { this.environment = environment; } protected FoodProcessorEnvironmentIF getEnvironment() { return environment; } public abstract String getName(); public abstract void start(); … }

  16. SD Dynamic Linkage (cont’)‏ Code Example (cont’)‏ public class FoodProcessorEnvironment implement FoodProcessorEnvironmentIF { private static final URL[] classPath; static { try { classPath = new URL{} {new URL(“file:///bin”)}; } catch (java.net.MailformedURLException e) { throw new ExceptionInIntializerError(e); } } public void slice(int width) { … } public double weigh() { double weight = 0.0; … return weight; }

  17. SD Dynamic Linkage (cont’)‏ Code Example (cont’)‏ void run(String programName) { URLClassLoader classLoader = new URLClassLoader(clasPath); Class programClass; try { programClass = classLoader.loadClass(programName); } catch (ClassNotFoundException e) { … return; } AbstractFoodProcessorProgram program; try { program = (AbstractFoodProcessorProgram)‏ programClass.newInstance(); } catch (Exception e) { … return; } program.setEnvironment(this); display(program.getName()); program.start(); } }

  18. SD Dynamic Linkage (cont’)‏ Code Example (cont’)‏ public class ConcreteFoodProcessorProgram extends AbstractFoodProcessorProgram { public String getName() { return “Chocolate Milk”; } public void start() { double weight = getEnvironment().weigh(); if (weight > 120.0 && weight < 160.0)‏ getEnvironment().mix(4); … } }

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

  20. SD Cache Management Synopsis Implement a cache. Context 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.

  21. SD Cache Management (cont’)‏ Structure Cache-objects-for CacheManager Cache fetchObject(:ObjectKey)‏ addObject(:Object)‏ fetchObject(:ObjectKey)‏ cacher ObjectKey Caches Create-objects-for-caching fetcher ObjectCreator Object createObject(:ObjectKey)‏

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

  23. SD 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 ObjectKey. search is more frequent from insert/remove so optimize for search… …however, there are also frequent insert/remove actions so should also be reasonable a hashtable is a good collection class

  24. SD Cache Management (cont’)‏ Code Example consider the Employee Timekeeping example: public class EmployeeProfileManager { private EmployeeCache cache = new EmployeeCache(); private EmployeeProfileFetcher server = new EmployeeProfileFetcher(); EmployeeProfile fetchEmployee(EmployeeID id) { EmployeeProfile profile = cache.fetchEmployee(id); if (profile == null) { profile = server.fetchEmployee(id); if (profile != null) { cache.addEmployee(profile); } } return profile; } }

  25. SD Cache Management (cont’)‏ Code Example (cont’)‏ class EmployeeCache { private Hashtable cache = new Hashtable(); LinkedList mru = null; LinkedList lru = null; private final int MAX_CACHE_SIZE = 80; private int currentCacheSize = 0; public EmployeeProfile fetchEmployee(EmployeeID id) { LinkedList foundLink = (LinkedList)cach.get(id); if (foundLink == null)‏ return null; if (mru != foundLink) { if (foundLink.previous != null)‏ foundLink.previous.next = foundLink.next; if (foundLink.next != null)‏ foundLink.next.previous = foundLink.previous; foundLink.previous = null; foundLink.next = mru; mru = foundLink; } return foundLink.profile; }

  26. SD Cache Management (cont’)‏ public void addEmployee(EmployeeProfile emp) { EmployeeID id = emp.getID(); if (cache.get(id) == null) { if (currentCacheSize == 0) { lru = mru = new LinkdList(); mru.profile = emp; } else { LinkedList newLink; if (currentCacheSzie >= MAX_CACHE_SIZE) { newLink = lru; lru = newLink.previous; cache.remove(newLink); lru.next = null; } else { newLink = new LinkedList(); } newLink.profile = emp; newLink.next = mru; newLink.previous = null; mru = newLink; } cache.put(id,mru); currentCacheSize++; } else { fetchEmployee(id); } }

  27. SD Cache Management (cont’)‏ Code example (cont’)‏ private class LinkedList { EmployeeProfile profile; LinkedList previous; } } class EmployeeProfile { private EmployeeID id; privtae Locale locale; private boolean supervisor; private String name; public EmployeeProfile(EmployeeID id,Locale locale, boolean supervisor, String name) { this.id = id; this.locale = locale; this.supervisor = supervisor; this.name = name; } public EmployeeID getID() { return id; } public Locale getLocale() { return locale; } public boolean isSupervisor() { return supervisor; } public String getName() { return name; } }

  28. SD Cache Management (cont’)‏ Code example (cont’)‏ class EmployeeID { private String id; public EmployeeID(String id) { this.id = id; } public int hashCode() { return id.hashCode(); } public boolean equals(Object obj) { return (obj instanceof EmployeeID && id.equals(((EmployeeID)obj).id) ); } public String toString() { return id; } }

  29. SD 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.

  30. SD Null Object Synopsis An alternative for using null to indicate the absence Context 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 do-nothing case to require any special code in the delegating class.

  31. SD Null Object (cont’)‏ Structure Participants Delegator delegates operations to AbstractOperation. doesn’t need to check for null. AbstractOperation defines the interface for operation. RealOpeation implements the operation NullOperation implements the operation as a no-op Delegator Uses AbstractOperation NullOperation RealOperation

  32. SD 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.

  33. SD Null Object (cont’)‏ Code Example consider the WarningRouter example: public interface WarningRouter { public boolean routeWarning(String msg); } class BusinessRule { private Warningrouter warning; private Date expirationDate = new Date(Long.MAX_VALUE); … BusinessRule() { … if (new Date().after(expirationDate)) { String msg = getClass().getName() + “ has expired.”; warning.routeWarning(msg); } … } }

  34. SD Null Object (cont’)‏ Code Example (cont’)‏ class WarningDialog implements WarningRouter { public boolean routeWarning(String warning) { int r; r = JOptionPane.showConfirmDialog(null, warning, “Warning”, JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); return r == 0; } } class IgnoreWarning implements WarningRouter { public boolean routeWarning(String warning) { return true; } }

  35. SD Null Object (cont’)‏ Related Patterns Singleton if instances of the NullOperation class contain no instance-specific information, then you can save time and memory by implementing NullOperation class as a singleton class. Strategy the Null Object pattern is often used with the Strategy pattern.

More Related