Skip to content

Commit 3356680

Browse files
committed
Added Lazy Loading idiom.
1 parent 484e1dd commit 3356680

File tree

11 files changed

+246
-2
lines changed

11 files changed

+246
-2
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ A programming idiom is a means of expressing a recurring construct in one or mor
7272
* [Double Checked Locking](#double-checked-locking)
7373
* [Poison Pill](#poison-pill)
7474
* [Callback](#callback)
75+
* [Lazy Loading](#lazy-loading)
7576

7677
## <a name="abstract-factory">Abstract Factory</a> [&#8593;](#list-of-design-patterns)
7778
**Intent:** Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
@@ -482,6 +483,19 @@ A programming idiom is a means of expressing a recurring construct in one or mor
482483
**Applicability:** Use the Poison Pill idiom when
483484
* need to send signal from one thread/process to another to terminate
484485

486+
## <a name="lazy-loading">Lazy Loading</a> [&#8593;](#list-of-design-patterns)
487+
**Intent:** Lazy loading is a design pattern commonly used to defer initialization of an object until the point at which it is needed. It can contribute to efficiency in the program's operation if properly and appropriately used.
488+
489+
![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/lazy-loading/etc/lazy-loading.png "Lazy Loading")
490+
491+
**Applicability:** Use the Lazy Loading idiom when
492+
* eager loading is expensive or the object to be loaded might not be need at all
493+
494+
**Real world examples:**
495+
* JPA annotations @OneToOne, @OneToMany, @ManyToOne, @ManyToMany and fetch = FetchType.LAZY
496+
497+
498+
485499
# Frequently asked questions
486500

487501
**<a id="Q1">Q: What is the difference between State and Strategy patterns?</a>**

lazy-loading/etc/lazy-loading.png

11.4 KB
Loading

lazy-loading/etc/lazy-loading.ucls

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
3+
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
4+
<class id="1" language="java" name="com.iluwatar.HolderNaive" project="lazy-loading"
5+
file="/lazy-loading/src/main/java/com/iluwatar/HolderNaive.java" binary="false" corner="BOTTOM_RIGHT">
6+
<position height="106" width="126" x="206" y="297"/>
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+
</class>
13+
<class id="2" language="java" name="com.iluwatar.Heavy" project="lazy-loading"
14+
file="/lazy-loading/src/main/java/com/iluwatar/Heavy.java" binary="false" corner="BOTTOM_RIGHT">
15+
<position height="88" width="104" x="289" y="479"/>
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.iluwatar.Java8Holder" project="lazy-loading"
23+
file="/lazy-loading/src/main/java/com/iluwatar/Java8Holder.java" binary="false" corner="BOTTOM_RIGHT">
24+
<position height="142" width="204" x="567" y="297"/>
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.iluwatar.HolderThreadSafe" project="lazy-loading"
32+
file="/lazy-loading/src/main/java/com/iluwatar/HolderThreadSafe.java" binary="false" corner="BOTTOM_RIGHT">
33+
<position height="106" width="155" x="372" y="297"/>
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+
<association id="5">
41+
<end type="SOURCE" refId="4" navigable="false">
42+
<attribute id="6" name="heavy"/>
43+
<multiplicity id="7" minimum="0" maximum="1"/>
44+
</end>
45+
<end type="TARGET" refId="2" navigable="true"/>
46+
<display labels="true" multiplicity="true"/>
47+
</association>
48+
<dependency id="8">
49+
<end type="SOURCE" refId="3"/>
50+
<end type="TARGET" refId="2"/>
51+
</dependency>
52+
<association id="9">
53+
<end type="SOURCE" refId="1" navigable="false">
54+
<attribute id="10" name="heavy"/>
55+
<multiplicity id="11" minimum="0" maximum="1"/>
56+
</end>
57+
<end type="TARGET" refId="2" navigable="true"/>
58+
<display labels="true" multiplicity="true"/>
59+
</association>
60+
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
61+
sort-features="false" accessors="true" visibility="true">
62+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
63+
<operations public="true" package="true" protected="true" private="true" static="true"/>
64+
</classifier-display>
65+
<association-display labels="true" multiplicity="true"/>
66+
</class-diagram>

lazy-loading/pom.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0"?>
2+
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>com.iluwatar</groupId>
7+
<artifactId>java-design-patterns</artifactId>
8+
<version>1.0-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>lazy-loading</artifactId>
11+
<dependencies>
12+
<dependency>
13+
<groupId>junit</groupId>
14+
<artifactId>junit</artifactId>
15+
<scope>test</scope>
16+
</dependency>
17+
</dependencies>
18+
</project>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.iluwatar;
2+
3+
/**
4+
*
5+
* Lazy loading idiom defers object creation until needed.
6+
*
7+
* This example shows different implementations of the pattern
8+
* with increasing sophistication.
9+
*
10+
* Additional information and lazy loading flavours are described in
11+
* http://martinfowler.com/eaaCatalog/lazyLoad.html
12+
*
13+
*/
14+
public class App
15+
{
16+
public static void main( String[] args ) {
17+
18+
// Simple lazy loader - not thread safe
19+
HolderNaive holderNaive = new HolderNaive();
20+
Heavy heavy = holderNaive.getHeavy();
21+
System.out.println("heavy=" + heavy);
22+
23+
// Thread safe lazy loader, but with heavy synchronization on each access
24+
HolderThreadSafe holderThreadSafe = new HolderThreadSafe();
25+
Heavy another = holderThreadSafe.getHeavy();
26+
System.out.println("another=" + another);
27+
28+
// The most efficient lazy loader utilizing Java 8 features
29+
Java8Holder java8Holder = new Java8Holder();
30+
Heavy next = java8Holder.getHeavy();
31+
System.out.println("next=" + next);
32+
}
33+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.iluwatar;
2+
3+
/**
4+
*
5+
* Heavy objects are expensive to create.
6+
*
7+
*/
8+
public class Heavy {
9+
10+
public Heavy() {
11+
System.out.println("Creating Heavy ...");
12+
try {
13+
Thread.sleep(1000);
14+
} catch (InterruptedException e) {
15+
e.printStackTrace();
16+
}
17+
System.out.println("... Heavy created");
18+
}
19+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.iluwatar;
2+
3+
/**
4+
*
5+
* Simple implementation of the lazy loading idiom.
6+
* However, this is not thread safe.
7+
*
8+
*/
9+
public class HolderNaive {
10+
11+
private Heavy heavy;
12+
13+
public HolderNaive() {
14+
System.out.println("HolderNaive created");
15+
}
16+
17+
public Heavy getHeavy() {
18+
if (heavy == null) {
19+
heavy = new Heavy();
20+
}
21+
return heavy;
22+
}
23+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.iluwatar;
2+
3+
/**
4+
*
5+
* Same as HolderNaive but with added synchronization.
6+
* This implementation is thread safe, but each {@link #getHeavy()}
7+
* call costs additional synchronization overhead.
8+
*
9+
*/
10+
public class HolderThreadSafe {
11+
12+
private Heavy heavy;
13+
14+
public HolderThreadSafe() {
15+
System.out.println("HolderThreadSafe created");
16+
}
17+
18+
public synchronized Heavy getHeavy() {
19+
if (heavy == null) {
20+
heavy = new Heavy();
21+
}
22+
return heavy;
23+
}
24+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.iluwatar;
2+
3+
import java.util.function.Supplier;
4+
5+
/**
6+
*
7+
* This lazy loader is thread safe and more efficient than HolderThreadSafe.
8+
* It utilizes Java 8 functional interface Supplier<T> as Heavy factory.
9+
*
10+
*/
11+
public class Java8Holder {
12+
13+
private Supplier<Heavy> heavy = () -> createAndCacheHeavy();
14+
15+
public Java8Holder() {
16+
System.out.println("Java8Holder created");
17+
}
18+
19+
public Heavy getHeavy() {
20+
return heavy.get();
21+
}
22+
23+
private synchronized Heavy createAndCacheHeavy() {
24+
class HeavyFactory implements Supplier<Heavy> {
25+
private final Heavy heavyInstance = new Heavy();
26+
@Override
27+
public Heavy get() { return heavyInstance; }
28+
}
29+
if (!HeavyFactory.class.isInstance(heavy)) {
30+
heavy = new HeavyFactory();
31+
}
32+
return heavy.get();
33+
}
34+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.iluwatar;
2+
3+
import org.junit.Test;
4+
5+
public class AppTest {
6+
7+
@Test
8+
public void test() {
9+
String[] args = {};
10+
App.main(args);
11+
}
12+
}

0 commit comments

Comments
 (0)