Added Lazy Loading idiom.

This commit is contained in:
Ilkka Seppala 2015-04-10 20:24:16 +03:00
parent 484e1ddfca
commit 33566805ee
11 changed files with 246 additions and 2 deletions

View File

@ -72,6 +72,7 @@ A programming idiom is a means of expressing a recurring construct in one or mor
* [Double Checked Locking](#double-checked-locking)
* [Poison Pill](#poison-pill)
* [Callback](#callback)
* [Lazy Loading](#lazy-loading)
## <a name="abstract-factory">Abstract Factory</a> [&#8593;](#list-of-design-patterns)
**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
**Applicability:** Use the Poison Pill idiom when
* need to send signal from one thread/process to another to terminate
## <a name="lazy-loading">Lazy Loading</a> [&#8593;](#list-of-design-patterns)
**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.
![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/lazy-loading/etc/lazy-loading.png "Lazy Loading")
**Applicability:** Use the Lazy Loading idiom when
* eager loading is expensive or the object to be loaded might not be need at all
**Real world examples:**
* JPA annotations @OneToOne, @OneToMany, @ManyToOne, @ManyToMany and fetch = FetchType.LAZY
# Frequently asked questions
**<a id="Q1">Q: What is the difference between State and Strategy patterns?</a>**

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
<class id="1" language="java" name="com.iluwatar.HolderNaive" project="lazy-loading"
file="/lazy-loading/src/main/java/com/iluwatar/HolderNaive.java" binary="false" corner="BOTTOM_RIGHT">
<position height="106" width="126" x="206" y="297"/>
<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="2" language="java" name="com.iluwatar.Heavy" project="lazy-loading"
file="/lazy-loading/src/main/java/com/iluwatar/Heavy.java" binary="false" corner="BOTTOM_RIGHT">
<position height="88" width="104" x="289" y="479"/>
<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.iluwatar.Java8Holder" project="lazy-loading"
file="/lazy-loading/src/main/java/com/iluwatar/Java8Holder.java" binary="false" corner="BOTTOM_RIGHT">
<position height="142" width="204" x="567" y="297"/>
<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.iluwatar.HolderThreadSafe" project="lazy-loading"
file="/lazy-loading/src/main/java/com/iluwatar/HolderThreadSafe.java" binary="false" corner="BOTTOM_RIGHT">
<position height="106" width="155" x="372" y="297"/>
<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>
<association id="5">
<end type="SOURCE" refId="4" navigable="false">
<attribute id="6" name="heavy"/>
<multiplicity id="7" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="2" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<dependency id="8">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="2"/>
</dependency>
<association id="9">
<end type="SOURCE" refId="1" navigable="false">
<attribute id="10" name="heavy"/>
<multiplicity id="11" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="2" 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>

18
lazy-loading/pom.xml Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0"?>
<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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>lazy-loading</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,33 @@
package com.iluwatar;
/**
*
* Lazy loading idiom defers object creation until needed.
*
* This example shows different implementations of the pattern
* with increasing sophistication.
*
* Additional information and lazy loading flavours are described in
* http://martinfowler.com/eaaCatalog/lazyLoad.html
*
*/
public class App
{
public static void main( String[] args ) {
// Simple lazy loader - not thread safe
HolderNaive holderNaive = new HolderNaive();
Heavy heavy = holderNaive.getHeavy();
System.out.println("heavy=" + heavy);
// Thread safe lazy loader, but with heavy synchronization on each access
HolderThreadSafe holderThreadSafe = new HolderThreadSafe();
Heavy another = holderThreadSafe.getHeavy();
System.out.println("another=" + another);
// The most efficient lazy loader utilizing Java 8 features
Java8Holder java8Holder = new Java8Holder();
Heavy next = java8Holder.getHeavy();
System.out.println("next=" + next);
}
}

View File

@ -0,0 +1,19 @@
package com.iluwatar;
/**
*
* Heavy objects are expensive to create.
*
*/
public class Heavy {
public Heavy() {
System.out.println("Creating Heavy ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("... Heavy created");
}
}

View File

@ -0,0 +1,23 @@
package com.iluwatar;
/**
*
* Simple implementation of the lazy loading idiom.
* However, this is not thread safe.
*
*/
public class HolderNaive {
private Heavy heavy;
public HolderNaive() {
System.out.println("HolderNaive created");
}
public Heavy getHeavy() {
if (heavy == null) {
heavy = new Heavy();
}
return heavy;
}
}

View File

@ -0,0 +1,24 @@
package com.iluwatar;
/**
*
* Same as HolderNaive but with added synchronization.
* This implementation is thread safe, but each {@link #getHeavy()}
* call costs additional synchronization overhead.
*
*/
public class HolderThreadSafe {
private Heavy heavy;
public HolderThreadSafe() {
System.out.println("HolderThreadSafe created");
}
public synchronized Heavy getHeavy() {
if (heavy == null) {
heavy = new Heavy();
}
return heavy;
}
}

View File

@ -0,0 +1,34 @@
package com.iluwatar;
import java.util.function.Supplier;
/**
*
* This lazy loader is thread safe and more efficient than HolderThreadSafe.
* It utilizes Java 8 functional interface Supplier<T> as Heavy factory.
*
*/
public class Java8Holder {
private Supplier<Heavy> heavy = () -> createAndCacheHeavy();
public Java8Holder() {
System.out.println("Java8Holder created");
}
public Heavy getHeavy() {
return heavy.get();
}
private synchronized Heavy createAndCacheHeavy() {
class HeavyFactory implements Supplier<Heavy> {
private final Heavy heavyInstance = new Heavy();
@Override
public Heavy get() { return heavyInstance; }
}
if (!HeavyFactory.class.isInstance(heavy)) {
heavy = new HeavyFactory();
}
return heavy.get();
}
}

View File

@ -0,0 +1,12 @@
package com.iluwatar;
import org.junit.Test;
public class AppTest {
@Test
public void test() {
String[] args = {};
App.main(args);
}
}

View File

@ -45,7 +45,8 @@
<module>property</module>
<module>intercepting-filter</module>
<module>poison-pill</module>
</modules>
<module>lazy-loading</module>
</modules>
<dependencyManagement>
<dependencies>
@ -73,4 +74,4 @@
</plugins>
</build>
</project>
</project>