@@ -19,6 +19,8 @@ As a real example of using this framework, see [TabShell](https://github.com/tec
1919 * [ Component Structure] ( #component-structure )
2020 * [ Component Lifecycle] ( #component-lifecycle )
2121 * [ Component Tree] ( #component-tree )
22+ * [ Imperative Component Management] ( #component-imperative )
23+ * [ Component Code Example] ( #component-code )
2224 * [ When to Create a Component?] ( #when-to-create-component )
2325 * [ When not to Create a Component?] ( #when-not-to-create-component )
2426* [ Requirements] ( #requirements )
@@ -187,67 +189,6 @@ since names like `FooViewComponent` and `FooViewModelComponent` are hardly conve
187189must be created: ` ChildView ` extends ` ParentView ` , ` ChildViewModel ` extends ` ParentViewModel ` , ` ChildComponent ` extends
188190` ParentComponent ` etc.
189191
190- Let’s look at some code demonstrating the use of these classes.
191-
192- ``` java
193-
194- public interface FooMediator extends ChildMediator {
195-
196- ...
197- }
198-
199- public class FooViewModel extends AbstractChildViewModel {
200-
201- ...
202-
203- @Override
204- public FooMediator getMediator () {
205- return (FooMediator ) super . getMediator();
206- }
207- }
208-
209- public class FooView extends AbstractChildView<FooViewModel > {
210-
211- public FooView (FooViewModel viewModel ) {
212- ...
213- }
214-
215- ...
216-
217- @Override
218- public FooComponent getComponent () {
219- return (FooComponent ) super . getComponent();
220- }
221- }
222-
223- public class FooComponent extends AbstractChildComponent<FooView > {
224-
225- protected class Mediator extends AbstractChildComponent .Mediator implements FooMediator {... }
226-
227- public FooComponent (FooView view ) {
228- ...
229- }
230-
231- ...
232-
233- @Override
234- public FooMediator createMediator () {
235- return new FooComponent .Mediator (); // the mediator is created at the beginning of initialization
236- }
237- }
238-
239- ```
240- This code demonstrates how to create a component instance.
241-
242- ``` java
243- var viewModel = new FooViewModel ();
244- var view = new FooView (viewModel);
245- var component = new FooComponent (view);
246- component. initialize();
247- ...
248- component. deinitialize();
249- ```
250-
251192Advantages of this approach:
252193
253194* Strict Separation. Using a ` Component ` together with a ` Mediator ` enforces a clear separation of layers according to
@@ -337,6 +278,124 @@ Keeping the component layer thin prevents it from becoming a God object and ensu
337278properly distributed between the View and the ViewModel. This constraint is essential for preserving architectural
338279clarity, testability, and long-term maintainability.
339280
281+ ### Imperative Component Management<a name =" component-imperative " ></a >
282+
283+ There are two main approaches to managing UI components: declarative and imperative. Each has its own strengths and
284+ weaknesses.
285+
286+ MVVM4FX adopts the imperative approach. In this approach, components are explicitly created, initialized, added to
287+ the component tree, and deinitialized by the developer. This choice leads to the following characteristics:
288+
289+ Strengths:
290+ - Clear ownership and responsibility boundaries for components.
291+ - Predictable and transparent initialization and deinitialization order.
292+ - Full control over component lifecycle and composition.
293+ - Natural support for dynamic UI scenarios (e.g., tabs, dialogs, docking layouts).
294+ - Reliable state persistence and restoration via component history.
295+ - Strict separation of concerns between ` Component ` , ` ComponentView ` , and ` ComponentViewModel ` .
296+
297+ Weaknesses:
298+ - Requires boilerplate code (though it is limited because components are typically large blocks such as editors,
299+ tabs, dialogs, or search panels).
300+ - Higher initial learning curve for developers new to the framework.
301+ - Careful design discipline needed to prevent overly complex or "God" components.
302+
303+ This approach ensures that MVVM4FX components behave predictably, remain testable, and can support complex,
304+ long-living, dynamic UI applications.
305+
306+ ### Component Code Example<a name =" component-code " ></a >
307+
308+ This example demonstrates the creation of a Foo component that dynamically adds a child Bar component.
309+
310+ ` ComponentMediator ` interface:
311+
312+ ``` java
313+
314+ public interface FooMediator extends ChildMediator {
315+
316+ void addBar (BarViewModel bar );
317+ }
318+ ```
319+
320+ ` ComponentViewModel ` class:
321+
322+ ``` java
323+ public class FooViewModel extends AbstractChildViewModel {
324+
325+ public void addBar () {
326+ var bar = new BarViewModel ();
327+ getMediator(). addBar(bar);
328+ }
329+
330+
331+ @Override
332+ public FooMediator getMediator () {
333+ return (FooMediator ) super . getMediator();
334+ }
335+
336+ ...
337+ }
338+ ```
339+
340+ ` ComponentView ` class:
341+
342+ ``` java
343+ public class FooView extends AbstractChildView<FooViewModel > {
344+
345+ public FooView (FooViewModel viewModel ) {
346+ ...
347+ }
348+
349+ ...
350+
351+ @Override
352+ public FooComponent getComponent () {
353+ return (FooComponent ) super . getComponent();
354+ }
355+ }
356+ ```
357+
358+ ` Component ` class:
359+
360+ ``` java
361+ public class FooComponent extends AbstractChildComponent<FooView > {
362+
363+ protected class Mediator extends AbstractChildComponent .Mediator implements FooMediator {
364+
365+ @Override
366+ public void addBar (BarViewModel vm ) {
367+ var v = new BarView (vm);
368+ var c = new BarComponent (v);
369+ c. initialize();
370+ addChild(c);
371+ getView. addSomewhere(v); // adding bar view into foo view
372+ }
373+ }
374+
375+ public FooComponent (FooView view ) {
376+ ...
377+ }
378+
379+ ...
380+
381+ @Override
382+ public FooMediator createMediator () {
383+ return new FooComponent .Mediator (); // the mediator is created at the beginning of initialization
384+ }
385+ }
386+ ```
387+
388+ This code demonstrates how to create the foo component instance:
389+
390+ ``` java
391+ var viewModel = new FooViewModel ();
392+ var view = new FooView (viewModel);
393+ var component = new FooComponent (view);
394+ component. initialize();
395+ ... // use the component
396+ component. deinitialize();
397+ ```
398+
340399### When to Create a Component? <a name =" when-to-create-component " ></a >
341400* The element has independent testable state or business logic that can exist without a ` View ` .
342401* The element has a distinct lifecycle requiring separate initialization/deinitialization, or can be dynamically
@@ -360,7 +419,15 @@ Java 11+ and JavaFX 19.
360419
361420## Dependencies <a name =" dependencies " ></a >
362421
363- The project will be added to the Maven Central repository in a few days.
422+ This project is available on Maven Central:
423+
424+ ```
425+ <dependency>
426+ <groupId>com.techsenger.mvvm4fx</groupId>
427+ <artifactId>mvvm4fx-core</artifactId>
428+ <version>${mvvm4fx.version}</version>
429+ </dependency>
430+ ```
364431
365432## Code Building <a name =" code-building " ></a >
366433
0 commit comments