codecentric AG Dusan Zamurovic A pattern discussion
Nov 22, 2014
codecentric AG
Dusan Zamurovic
A pattern discussion
codecentric AG
- Singleton pattern- things we sometimes forget
- Dependency injection / Inversion of Control- Paired with Singleton- Example without third party library
TOPICS
codecentric AG
- What Singleton pattern does?- Implementation examples
- Wrong implementations- Implementations that look okay- Right implementations
Singleton
codecentric AG
Singleton 01
public class Singleton01 { // TODO Make this class final?
private static Singleton01 instance = null;
private Singleton01() { // Private constructor prevents instantiation, // but also prevents sub-classing. }
public static Singleton01 getInstance() { if (instance == null) { instance = new Singleton01(); } return instance; }
}
codecentric AG
Singleton 02
private static Singleton02 instance = null;
public static Singleton02 getInstance() { if (instance == null) { simulateMultiThreadEnvironment(); instance = new Singleton02(); }
return instance;}
// Not synchronized, not thread safe.
codecentric AG
Singleton 03
private static Singleton03 instance = null; public synchronized static Singleton03 getInstance() { if (instance == null) { simulateMultiThreadEnvironment(); instance = new Singleton03(); }
return instance;}
// Synchronized, thread safe.
codecentric AG
Singleton 04
private static Singleton04 instance = null;
public static Singleton04 getInstance() { if (instance == null) { synchronized (Singleton04.class) { simulateMultiThreadEnvironment(); instance = new Singleton04(); } } return instance;}
// Synchronized, performance optimization, not thread safe.
codecentric AG
Singleton 05
private static Singleton05 instance = null;
public static Singleton05 getInstance() { if (instance == null) { synchronized (Singleton05.class) { if (instance == null) { instance = new Singleton05(); } } } return instance;}
// Double-checked locking – doesn’t work prior to Java 1.5.
codecentric AG
Singleton 06
private static final Singleton06 INSTANCE = new Singleton06();
public static Singleton06 getInstance() { return INSTANCE;}
// Eager instantiating of the class. This works.
// What about serialization/deserialization?
codecentric AG
Singleton 06 Serializable
public class Singleton06 implements Serializable {
private static final Singleton06 INSTANCE = new Singleton06();
public static Singleton06 getInstance() { return INSTANCE; }
}
protected Object readResolve() { return getInstance();}
codecentric AG
Singleton 07
public enum Singleton07 {
INSTANCE;
}
// What about serialization/deserialization?
// What about reflection?
codecentric AG
- What is DI / IoC?
- Implementation example- No third party library
Dependency Injection / Inversion of Control
codecentric AG
Dependency Injection / Inversion of Control
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Component {
}
@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface Inject {
}
// @Component is used to mark a class – a thing to inject.
// @Inject is used to mark a field – a place to inject.
codecentric AG
Dependency Injection / Inversion of Control
@Componentpublic class Controller {
@Inject private ManageCapable manager;
…}
@Componentpublic class Manager implements ManageCapable {
@Inject private Repository repository;
…}
codecentric AG
Dependency Injection / Inversion of Control
@Componentpublic class Repository {
public Resourcable save(Resourcable aResource) { // Here we "persist" the given resource // and return it like we really did it. return aResource; }}
codecentric AG
Dependency Injection / Inversion of Control
public class PackageScanner { …}
public class ClassScanner { …}
public class DependencyInjectionManager { …}
// https://github.com/dzamurovic/meetup_singleton.git
codecentric AG
Dependency Injection / Inversion of Control
public synchronized void run() throws Exception { if (initialized) { return; } // Find classes annotated with @Component. List<Class> components = packageScanner.findAnnotatedClasses( "rs.codecentric.meetup.diioc.example", Component.class);
// For each component... for (Class component : components) { Class definingClass = classScanner.getDefiningClass(component); // ... check if its instance already exists... if (!graph.containsKey(definingClass)) { // ... and instantiate it, if it doesn't. String className = component.getName(); graph.put(definingClass, Class.forName(component.getName()).newInstance()); } } }
codecentric AG
Dependency Injection / Inversion of Control
// For each object that is created... for (Iterator<Class> classIterator = graph.keySet().iterator(); classIterator.hasNext();) { Class definingClass = classIterator.next(); Object object = graph.get(definingClass);
// ... find dependencies it needs, ... for (Field f : classScanner.findAnnotatedFields(object.getClass(), Inject.class)) { if (!graph.containsKey(f.getType())) { // ... throw an error if a dependency cannot be satisfied, ... } // ... or set a value of the dependency. Object dependency = graph.get(f.getType()); f.set(object, dependency);
} }
initialized = true;
}
codecentric AG
Dependency Injection / Inversion of Control
public static void main(String args[]) throws Exception { final DependencyInjectionManager diManager = DependencyInjectionManager.getInstance();
Thread t1 = new DependencyInjectionThread("DI-thread-0", diManager); Thread t2 = …
t1.start(); t2.st…
t1.join(); t2.j…
diManager.describeDependencyGraph();}
codecentric AG
QUESTIONS?
https://github.com/dzamurovic/meetup_singleton.git
@ezamur
@CodingSerbia
http://www.meetup.com/Coding-Serbia/
www.codecentric.de
www.codecentric.rs
https://blog.codecentric.de
04/08/2023 20