Merge branch 'MSaifAsif-master'
This commit is contained in:
commit
3ef1613fa6
13
README.md
13
README.md
@ -21,6 +21,7 @@
|
||||
* [Facade](#facade)
|
||||
* [Flyweight](#flyweight)
|
||||
* [Proxy](#proxy)
|
||||
* [Service Locator](#service-locator)
|
||||
* Behavioral Patterns
|
||||
* [Chain of responsibility](#chain-of-responsibility)
|
||||
* [Command](#command)
|
||||
@ -174,6 +175,18 @@
|
||||
* facilitate network connection
|
||||
* to count references to an object
|
||||
|
||||
## <a name="service-locator">Service Locator</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** Encapsulate the processes involved in obtaining a service with a strong abstraction layer.
|
||||
|
||||

|
||||
|
||||
**Applicability:** The service locator pattern is applicable whenever we want to locate/fetch various services using JNDI which, typically, is a redundant and expensive lookup. The service Locator pattern addresses this expensive lookup by making use of caching techniques ie. for the very first time a particular service is requested, the service Locator looks up in JNDI, fetched the relavant service and then finally caches this service object. Now, further lookups of the same service via Service Locator is done in its cache which improves the performance of application to great extent.
|
||||
|
||||
**Typical Use Case:**
|
||||
|
||||
* When network hits are expensive and time consuming
|
||||
* lookups of services are done quite frequently
|
||||
* large number of services are being used
|
||||
|
||||
## <a name="chain-of-responsibility">Chain of responsibility</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
|
||||
|
1
pom.xml
1
pom.xml
@ -37,6 +37,7 @@
|
||||
<module>visitor</module>
|
||||
<module>double-checked-locking</module>
|
||||
<module>servant</module>
|
||||
<module>service-locator</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
|
74
service-locator/etc/model.ucls
Normal file
74
service-locator/etc/model.ucls
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.7" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
|
||||
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
|
||||
<interface id="1" language="java" name="com.iluwater.Service" project="service-locator"
|
||||
file="/service-locator/src/main/java/com/iluwater/Service.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="110" y="182"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<class id="2" language="java" name="com.iluwater.ServiceImpl" project="service-locator"
|
||||
file="/service-locator/src/main/java/com/iluwater/ServiceImpl.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="342" y="374"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="3" language="java" name="com.iluwater.ServiceLocator" project="service-locator"
|
||||
file="/service-locator/src/main/java/com/iluwater/ServiceLocator.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="702" y="175"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="4" language="java" name="com.iluwater.ServiceCache" project="service-locator"
|
||||
file="/service-locator/src/main/java/com/iluwater/ServiceCache.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="397" y="81"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<realization id="5">
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</realization>
|
||||
<association id="6">
|
||||
<end type="SOURCE" refId="3" navigable="false">
|
||||
<attribute id="7" name="serviceCache">
|
||||
<position height="0" width="0" x="0" y="0"/>
|
||||
</attribute>
|
||||
<multiplicity id="8" minimum="0" maximum="1">
|
||||
<position height="0" width="0" x="0" y="0"/>
|
||||
</multiplicity>
|
||||
</end>
|
||||
<end type="TARGET" refId="4" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<association id="9">
|
||||
<end type="SOURCE" refId="4" navigable="false">
|
||||
<attribute id="10" name="serviceCache">
|
||||
<position height="0" width="0" x="0" y="0"/>
|
||||
</attribute>
|
||||
<multiplicity id="11" minimum="0" maximum="2147483647">
|
||||
<position height="0" width="0" x="0" y="0"/>
|
||||
</multiplicity>
|
||||
</end>
|
||||
<end type="TARGET" refId="1" navigable="true"/>
|
||||
<display labels="true" multiplicity="true"/>
|
||||
</association>
|
||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</classifier-display>
|
||||
<association-display labels="true" multiplicity="true"/>
|
||||
</class-diagram>
|
BIN
service-locator/etc/service-locator.png
Normal file
BIN
service-locator/etc/service-locator.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
9
service-locator/pom.xml
Normal file
9
service-locator/pom.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>service-locator</artifactId>
|
||||
</project>
|
20
service-locator/src/main/java/com/iluwater/App.java
Normal file
20
service-locator/src/main/java/com/iluwater/App.java
Normal file
@ -0,0 +1,20 @@
|
||||
package com.iluwater;
|
||||
/**
|
||||
* Service locator pattern, used to lookup jndi services
|
||||
* and cache them for subsequent requests.
|
||||
* @author saifasif
|
||||
*
|
||||
*/
|
||||
public class App {
|
||||
public static void main(String[] args) {
|
||||
Service service = ServiceLocator.getService("jndi/serviceA");
|
||||
service.execute();
|
||||
service = ServiceLocator.getService("jndi/serviceB");
|
||||
service.execute();
|
||||
service = ServiceLocator.getService("jndi/serviceA");
|
||||
service.execute();
|
||||
service = ServiceLocator.getService("jndi/serviceA");
|
||||
service.execute();
|
||||
}
|
||||
|
||||
}
|
29
service-locator/src/main/java/com/iluwater/InitContext.java
Normal file
29
service-locator/src/main/java/com/iluwater/InitContext.java
Normal file
@ -0,0 +1,29 @@
|
||||
package com.iluwater;
|
||||
|
||||
/**
|
||||
* For JNDI lookup of services from the web.xml. Will match name of the service name that
|
||||
* is being requested and return a newly created service object with the name
|
||||
* @author saifasif
|
||||
*
|
||||
*/
|
||||
public class InitContext {
|
||||
|
||||
/**
|
||||
* Perform the lookup based on the service name. The returned object will need to be
|
||||
* casted into a {@link Service}
|
||||
* @param serviceName
|
||||
* @return
|
||||
*/
|
||||
public Object lookup(String serviceName){
|
||||
if( serviceName.equals("jndi/serviceA") ){
|
||||
System.out.println("Looking up service A and creating new serivce for A");
|
||||
return new ServiceImpl("jndi/serviceA");
|
||||
} else if( serviceName.equals("jndi/serviceB") ){
|
||||
System.out.println("Looking up service B and creating new serivce for B");
|
||||
return new ServiceImpl("jndi/serviceB");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
29
service-locator/src/main/java/com/iluwater/Service.java
Normal file
29
service-locator/src/main/java/com/iluwater/Service.java
Normal file
@ -0,0 +1,29 @@
|
||||
package com.iluwater;
|
||||
|
||||
/**
|
||||
* This is going to be the parent service interface which we will
|
||||
* use to create our services. All services will have a
|
||||
* <li>service name</li>
|
||||
* <li>unique id</li>
|
||||
* <li>execution work flow</li>
|
||||
* @author saifasif
|
||||
*
|
||||
*/
|
||||
public interface Service {
|
||||
|
||||
/*
|
||||
* The human readable name of the service
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/*
|
||||
* Unique ID of the particular service
|
||||
*/
|
||||
public int getId();
|
||||
|
||||
/*
|
||||
* The workflow method that defines what this service does
|
||||
*/
|
||||
public void execute();
|
||||
|
||||
}
|
46
service-locator/src/main/java/com/iluwater/ServiceCache.java
Normal file
46
service-locator/src/main/java/com/iluwater/ServiceCache.java
Normal file
@ -0,0 +1,46 @@
|
||||
package com.iluwater;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The service cache implementation which will cache services that are being created.
|
||||
* On first hit, the cache will be empty and thus any service that is being requested, will be
|
||||
* created fresh and then placed into the cache map. On next hit, if same service name will
|
||||
* be requested, it will be returned from the cache
|
||||
* @author saifasif
|
||||
*
|
||||
*/
|
||||
public class ServiceCache {
|
||||
|
||||
private Map<String, Service> serviceCache;
|
||||
|
||||
public ServiceCache() {
|
||||
serviceCache = new HashMap<String, Service>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the service from the cache. null if no service is found matching the
|
||||
* name
|
||||
* @param serviceName
|
||||
* @return {@link Service}
|
||||
*/
|
||||
public Service getService(String serviceName){
|
||||
Service cachedService = null;
|
||||
for (String serviceJndiName : serviceCache.keySet()){
|
||||
if( serviceJndiName.equals( serviceName ) ){
|
||||
cachedService = serviceCache.get(serviceJndiName);
|
||||
System.out.println("(cache call) Fetched service " + cachedService.getName() + "("+cachedService.getId()+") from cache... !");
|
||||
}
|
||||
}
|
||||
return cachedService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the service into the cache map
|
||||
* @param newService
|
||||
*/
|
||||
public void addService(Service newService){
|
||||
serviceCache.put(newService.getName(), newService);
|
||||
}
|
||||
}
|
37
service-locator/src/main/java/com/iluwater/ServiceImpl.java
Normal file
37
service-locator/src/main/java/com/iluwater/ServiceImpl.java
Normal file
@ -0,0 +1,37 @@
|
||||
package com.iluwater;
|
||||
|
||||
/**
|
||||
* This is a single service implementation of a sample service. This is the actual
|
||||
* service that will process the request. The reference for this service is to
|
||||
* be looked upon in the JNDI server that can be set in the web.xml deployment descriptor
|
||||
* @author saifasif
|
||||
*
|
||||
*/
|
||||
public class ServiceImpl implements Service {
|
||||
|
||||
private String serviceName;
|
||||
private int id;
|
||||
|
||||
public ServiceImpl(String serviceName) {
|
||||
// set the service name
|
||||
this.serviceName = serviceName;
|
||||
|
||||
// Generate a random id to this service object
|
||||
this.id = (int)Math.floor(Math.random()*1000)+1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
System.out.println("Service " + getName() + " is now executing with id " + getId());
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.iluwater;
|
||||
|
||||
/**
|
||||
* The service locator module.
|
||||
* Will fetch service from cache, otherwise creats a fresh service and update cache
|
||||
*
|
||||
* @author saifasif
|
||||
*
|
||||
*/
|
||||
public class ServiceLocator {
|
||||
|
||||
private static ServiceCache serviceCache = new ServiceCache();
|
||||
|
||||
/**
|
||||
* Fetch the service with the name param from the cache first,
|
||||
* if no service is found, lookup the service from the {@link InitContext} and
|
||||
* then add the newly created service into the cache map for future requests.
|
||||
* @param serviceJndiName
|
||||
* @return {@link Service}
|
||||
*/
|
||||
public static Service getService(String serviceJndiName){
|
||||
Service serviceObj = serviceCache.getService(serviceJndiName);
|
||||
if ( serviceObj != null ){
|
||||
return serviceObj;
|
||||
} else {
|
||||
/*
|
||||
* If we are unable to retrive anything from cache, then
|
||||
* lookup the service and add it in the cache map
|
||||
*/
|
||||
InitContext ctx = new InitContext();
|
||||
serviceObj = (Service) ctx.lookup(serviceJndiName);
|
||||
serviceCache.addService(serviceObj);
|
||||
return serviceObj;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user