8000 Merge branch 'MSaifAsif-master' · mavencode01/java-design-patterns@3ef1613 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3ef1613

Browse files
committed
Merge branch 'MSaifAsif-master'
2 parents 2939d13 + 5d142fb commit 3ef1613

File tree

11 files changed

+295
-0
lines changed

11 files changed

+295
-0
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
* [Facade](#facade)
2222
* [Flyweight](#flyweight)
2323
* [Proxy](#proxy)
24+
* [Service Locator](#service-locator)
2425
* Behavioral Patterns
2526
* [Chain of responsibility](#chain-of-responsibility)
2627
* [Command](#command)
@@ -174,6 +175,18 @@
174175
* facilitate network connection
175176
* to count references to an object
176177

178+
## <a name="service-locator">Service Locator</a> [&#8593;](#list-of-design-patterns)
179+
**Intent:** Encapsulate the processes involved in obtaining a service with a strong abstraction layer.
180+
181+
![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/service-locator/etc/service-locator.png "Proxy")
182+
183+
**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.
184+
185+
**Typical Use Case:**
186+
187+
* When network hits are expensive and time consuming
188+
* lookups of services are done quite frequently
189+
* large number of services are being used
177190

178191
## <a name="chain-of-responsibility">Chain of responsibility</a> [&#8593;](#list-of-design-patterns)
179192
**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.

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
<module>visitor</module>
3838
<module>double-checked-locking</module>
3939
<module>servant</module>
40+
<module>service-locator</module>
4041
</modules>
4142

4243
<build>

service-locator/etc/model.ucls

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<class-diagram version="1.1.7" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
3+
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
4+
<interface id="1" language="java" name="com.iluwater.Service" project="service-locator"
5+
file="/service-locator/src/main/java/com/iluwater/Service.java" binary="false" corner="BOTTOM_RIGHT">
6+
<position height="-1" width="-1" x="110" y="182"/>
7+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
8+
sort-features="false" accessors="true" visibility="true">
9+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
10+
<operations public="true" package="true" protected="true" private="true" static="true"/>
11+
</display>
12+
</interface>
13+
<class id="2" language="java" name="com.iluwater.ServiceImpl" project="service-locator"
14+
file="/service-locator/src/main/java/com/iluwater/ServiceImpl.java" binary="false" corner="BOTTOM_RIGHT">
15+
<position height="-1" width="-1" x="342" y="374"/>
16+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
17+
sort-features="false" accessors="true" visibility="true">
18+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
19+
<operations public="true" package="true" protected="true" private="true" static="true"/>
20+
</display>
21+
</class>
22+
<class id="3" language="java" name="com.iluwater.ServiceLocator" project="service-locator"
23+
file="/service-locator/src/main/java/com/iluwater/ServiceLocator.java" binary="false" corner="BOTTOM_RIGHT">
24+
<position height="-1" width="-1" x="702" y="175"/>
25+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
26+
sort-features="false" accessors="true" visibility="true">
27+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
28+
<operations public="true" package="true" protected="true" private="true" static="true"/>
29+
</display>
30+
</class>
31+
<class id="4" language="java" name="com.iluwater.ServiceCache" project="service-locator"
32+
file="/service-locator/src/main/java/com/iluwater/ServiceCache.java" binary="false" corner="BOTTOM_RIGHT">
33+
<position height="-1" width="-1" x="397" y="81"/>
34+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
35+
sort-features="false" accessors="true" visibility="true">
36+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
37+
<operations public="true" package="true" protected="true" private="true" static="true"/>
38+
</display>
39+
</class>
40+
<realization id="5">
41+
<end type="SOURCE" refId="2"/>
42+
<end type="TARGET" refId="1"/>
43+
</realization>
44+
<association id="6">
45+
<end type="SOURCE" refId="3" navigable="false">
46+
<attribute id="7" name="serviceCache">
47+
<position height="0" width="0" x="0" y="0"/>
48+
</attribute>
49+
<multiplicity id="8" minimum="0" maximum="1">
50+
<position height="0" width="0" x="0" y="0"/>
51+
</multiplicity>
52+
</end>
53+
<end type="TARGET" refId="4" navigable="true"/>
54+
<display labels="true" multiplicity="true"/>
55+
</association>
56+
<association id="9">
57+
<end type="SOURCE" refId="4" navigable="false">
58+
<attribute id="10" name="serviceCache">
59+
<position height="0" width="0" x="0" y="0"/>
60+
</attribute>
61+
<multiplicity id="11" minimum="0" maximum="2147483647">
62+
<position height="0" width="0" x="0" y="0"/>
63+
</multiplicity>
64+
</end>
65+
<end type="TARGET" refId="1" navigable="true"/>
66+
<display labels="true" multiplicity="true"/>
67+
</association>
68+
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
69+
sort-features="false" accessors="true" visibility="true">
70+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
71+
<operations public="true" package="true" protected="true" private="true" static="true"/>
72+
</classifier-display>
73+
<association-display labels="true" multiplicity="true"/>
74+
</class-diagram>
37.3 KB
Loading

service-locator/pom.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<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">
2+
<modelVersion>4.0.0</modelVersion>
3+
<parent>
4+
<groupId>com.iluwatar</groupId>
5+
<artifactId>java-design-patterns</artifactId>
6+
<version>1.0-SNAPSHOT</version>
7+
</parent>
8+
<artifactId>service-locator</artifactId>
9+
</project>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.iluwater;
2+
/**
3+
* Service locator pattern, used to lookup jndi services
4+
* and cache them for subsequent requests.
5+
* @author saifasif
6+
*
7+
*/
8+
public class App {
9+
public static void main(String[] args) {
10+
Service service = ServiceLocator.getService("jndi/serviceA");
11+
service.execute();
12+
service = ServiceLocator.getService("jndi/serviceB");
13+
service.execute();
14+
service = ServiceLocator.getService("jndi/serviceA");
15+
service.execute();
16+
service = ServiceLocator.getService("jndi/serviceA");
17+
service.execute();
18+
}
19+
20+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.iluwater;
2+
3+
/**
4+
* For JNDI lookup of services from the web.xml. Will match name of the service name that
5+
* is being requested and return a newly created service object with the name
6+
* @author saifasif
7+
*
8+
*/
9+
public class InitContext {
10+
11+
/**
12+
* Perform the lookup based on the service name. The returned object will need to be
13+
* casted into a {@link Service}
14+
* @param serviceName
15+
* @return
16+
*/
17+
public Object lookup(String serviceName){
18+
if( serviceName.equals("jndi/serviceA") ){
19+
System.out.println("Looking up service A and creating new serivce for A");
20+
return new ServiceImpl("jndi/serviceA");
21+
} else if( serviceName.equals("jndi/serviceB") ){
22+
System.out.println("Looking up service B and creating new serivce for B");
23+
return new ServiceImpl("jndi/serviceB");
24+
} else {
25+
return null;
26+
}
27+
}
28+
29+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.iluwater;
2+
3+
/**
4+
* This is going to be the parent service interface which we will
5+
* use to create our services. All services will have a
6+
* <li>service name</li>
7+
* <li>unique id</li>
8+
* <li>execution work flow</li>
9+
* @author saifasif
10+
*
11+
*/
12+
public interface Service {
13+
14+
/*
15+
* The human readable name of the service
16+
*/
17+
public String getName();
18+
19+
/*
20+
* Unique ID of the particular service
21+
*/
22+
public int getId();
23+
24+
/*
25+
* The workflow method that defines what this service does
26+
*/
27+
public void execute();
28+
29+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.iluwater;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* The service cache implementation which will cache services that are being created.
8+
* On first hit, the cache will be empty and thus any service that is being requested, will be
9+
* created fresh and then placed into the cache map. On next hit, if same service name will
10+
* be requested, it will be returned from the cache
11+
* @author saifasif
12+
*
13+
*/
14+
public class ServiceCache {
15+
16+
private Map<String, Service> serviceCache;
17+
18+
public ServiceCache() {
19+
serviceCache = new HashMap<String, Service>();
20+
}
21+
22+
/**
23+
* Get the service from the cache. null if no service is found matching the
24+
* name
25+
* @param serviceName
26+
* @return {@link Service}
27+
*/
28+
public Service getService(String serviceName){
29+
Service cachedService = null;
30+
for (String serviceJndiName : serviceCache.keySet()){
31+
if( serviceJndiName.equals( serviceName ) ){
32+
cachedService = serviceCache.get(serviceJndiName);
33+
System.out.println("(cache call) Fetched service " + cachedService.getName() + "("+cachedService.getId()+") from cache... !");
34+
}
35+
}
36+
return cachedService;
37+
}
38+
39+
/**
40+
* Adds the service into the cache map
41+
* @param newService
42+
*/
43+
public void addService(Service newService){
44+
serviceCache.put(newService.getName(), newService);
45+
}
46+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.iluwater;
2+
3+
/**
4+
* This is a single service implementation of a sample service. This is the actual
5+
* service that will process the request. The reference for this service is to
6+
* be looked upon in the JNDI server that can be set in the web.xml deployment descriptor
7+
* @author saifasif
8+
*
9+
*/
10+
public class ServiceImpl implements Service {
11+
12+
private String serviceName;
13+
private int id;
14+
15+
public ServiceImpl(String serviceName) {
16+
// set the service name
17+
this.serviceName = serviceName;
18+
19+
// Generate a random id to this service object
20+
this.id = (int)Math.floor(Math.random()*1000)+1;
21+
}
22+
23+
@Override
24+
public String getName() {
25+
return serviceName;
26+
}
27+
28+
@Override
29+
public int getId() {
30+
return id;
31+
}
32+
33+
@Override
34+
public void execute() {
35+
System.out.println("Service " + getName() + " is now executing with id " + getId());
36+
}
37+
}

0 commit comments

Comments
 (0)
0