001package jmri; 002 003/** 004 * Provide a hint to the {@link jmri.InstanceManager} that this object needs 005 * have additional initialization performed after the InstanceManager initially 006 * creates it. This allows two classes that have circular dependencies on 007 * being able to get the default instance of each other to be managed 008 * successfully. 009 * <p> 010 * More specifically, the constructors or code called by the constructors 011 * of classes implementing the {@link InstanceManagerAutoDefault} interface 012 * (i.e. that have the InstanceManager automatically 013 * create their objects) should never ask the InstanceManager for reference to other 014 * automatically-created types. They may ask the InstanceManager for references in their 015 * {@link #initialize()} method, but they can only store those; they can't assume 016 * that the objects referred to have completed their initialization and are operational. 017 * See the diagram below for why. 018 * <p> 019 * Note: the need to have a class implement this probably is indicative of other 020 * design issues in the implementing class and its dependencies. 021 * <p> 022 * <img src="doc-files/InstanceManagerAutoInitialize-Sequence.png" alt="Initialization sequence UML diagram"> 023 * 024 * @author Randall Wood Copyright 2017 025 */ 026public interface InstanceManagerAutoInitialize { 027 028 /** 029 * Perform any initialization that occurs after this object has been 030 * constructed and made available by the InstanceManager. 031 */ 032 void initialize(); 033 034} 035 036/* 037 * @startuml jmri/doc-files/InstanceManagerAutoInitialize-Sequence.png 038 * participant Client 039 * participant InstanceManager 040 * participant ClassA 041 * participant ClassB 042 * 043 * Client -> InstanceManager : getDefault(ClassA) 044 * activate InstanceManager 045 * note over InstanceManager : Doesn't have a ClassA instance 046 * 047 * InstanceManager o-> ClassA : new InstanceManagerAutoDefault#ClassA() 048 * activate ClassA 049 * InstanceManager <-- ClassA : return new ClassA instance 050 * deactivate ClassA 051 * note over InstanceManager : Adds ClassA to list\nso it's available 052 * InstanceManager -> ClassA : InstanceManagerAutoInitialize#initialize() 053 * activate ClassA 054 * note over ClassA : It's safe here to\nask for a ClassB\nreference 055 * 056 * ClassA -> InstanceManager : getDefault(ClassB) 057 * activate InstanceManager 058 * note over InstanceManager : Doesn't have a ClassB instance 059 * InstanceManager o-> ClassB : new InstanceManagerAutoDefault#ClassB() 060 * activate ClassB 061 * InstanceManager <-- ClassB : return new ClassB instance 062 * deactivate ClassB 063 * note over InstanceManager : Adds ClassB to list\nso it's available 064 * InstanceManager -> ClassB : InstanceManagerAutoInitialize#initialize() 065 * activate ClassB 066 * 067 * note over ClassB : It's safe here to\nask for a ClassA\nreference 068 * 069 * ClassB -> InstanceManager : getDefault(ClassA) 070 * activate InstanceManager 071 * note over InstanceManager : Has a ClassA instance,\nthough initialize() is\nnot yet complete 072 * ClassB <-- InstanceManager : return existing ClassA instance 073 * deactivate InstanceManager 074 * 075 * note over ClassB : but not yet to ask\nClassA to operate 076 * InstanceManager <-- ClassB 077 * deactivate ClassB 078 * 079 * 080 * 081 * InstanceManager <-- ClassA 082 * deactivate ClassA 083 * 084 * Client <-- InstanceManager : return new ClassA instance 085 * deactivate InstanceManager 086 * 087 * 088 * @enduml 089 */