Families of cross-platform GUI components and their production
In this example, buttons and checkboxes will act as products. They have two variants: macOS and Windows.
The abstract factory defines an interface for creating buttons and checkboxes. There are two concrete factories, which return both products in a single variant.
Client code works with factories and products using abstract interfaces. It makes the same client code working with many product variants, depending on the type of factory object.
buttons: First product hierarchy
buttons/Button.java
packagerefactoring_guru.abstract_factory.example.buttons;/** * Abstract Factory assumes that you have several families of products, * structured into separate class hierarchies (Button/Checkbox). All products of * the same family have the common interface. * * This is the common interface for buttons family. */publicinterfaceButton {voidpaint();}
buttons/MacOSButton.java
packagerefactoring_guru.abstract_factory.example.buttons;/** * All products families have the same varieties (MacOS/Windows). * * This is a MacOS variant of a button. */publicclassMacOSButtonimplementsButton { @Overridepublicvoidpaint() {System.out.println("You have created MacOSButton."); }}
buttons/WindowsButton.java
packagerefactoring_guru.abstract_factory.example.buttons;/** * All products families have the same varieties (MacOS/Windows). * * This is another variant of a button. */publicclassWindowsButtonimplementsButton { @Overridepublicvoidpaint() {System.out.println("You have created WindowsButton."); }}
checkboxes: Second product hierarchy
checkboxes/Checkbox.java
packagerefactoring_guru.abstract_factory.example.checkboxes;/** * Checkboxes is the second product family. It has the same variants as buttons. */publicinterfaceCheckbox {voidpaint();}
checkboxes/MacOSCheckbox.java
packagerefactoring_guru.abstract_factory.example.checkboxes;/** * All products families have the same varieties (MacOS/Windows). * * This is a variant of a checkbox. */publicclassMacOSCheckboximplementsCheckbox { @Overridepublicvoidpaint() {System.out.println("You have created MacOSCheckbox."); }}
checkboxes/WindowsCheckbox.java
packagerefactoring_guru.abstract_factory.example.checkboxes;/** * All products families have the same varieties (MacOS/Windows). * * This is another variant of a checkbox. */publicclassWindowsCheckboximplementsCheckbox { @Overridepublicvoidpaint() {System.out.println("You have created WindowsCheckbox."); }}
factories
factories/GUIFactory.java: Abstract factory
packagerefactoring_guru.abstract_factory.example.factories;importrefactoring_guru.abstract_factory.example.buttons.Button;importrefactoring_guru.abstract_factory.example.checkboxes.Checkbox;/** * Abstract factory knows about all (abstract) product types. */publicinterfaceGUIFactory {ButtoncreateButton();CheckboxcreateCheckbox();}
packagerefactoring_guru.abstract_factory.example.factories;importrefactoring_guru.abstract_factory.example.buttons.Button;importrefactoring_guru.abstract_factory.example.buttons.MacOSButton;importrefactoring_guru.abstract_factory.example.checkboxes.Checkbox;importrefactoring_guru.abstract_factory.example.checkboxes.MacOSCheckbox;/** * Each concrete factory extends basic factory and responsible for creating * products of a single variety. */publicclassMacOSFactoryimplementsGUIFactory { @OverridepublicButtoncreateButton() {returnnewMacOSButton(); } @OverridepublicCheckboxcreateCheckbox() {returnnewMacOSCheckbox(); }}
packagerefactoring_guru.abstract_factory.example.factories;importrefactoring_guru.abstract_factory.example.buttons.Button;importrefactoring_guru.abstract_factory.example.buttons.WindowsButton;importrefactoring_guru.abstract_factory.example.checkboxes.Checkbox;importrefactoring_guru.abstract_factory.example.checkboxes.WindowsCheckbox;/** * Each concrete factory extends basic factory and responsible for creating * products of a single variety. */publicclassWindowsFactoryimplementsGUIFactory { @OverridepublicButtoncreateButton() {returnnewWindowsButton(); } @OverridepublicCheckboxcreateCheckbox() {returnnewWindowsCheckbox(); }}
app
app/Application.java: Client code
packagerefactoring_guru.abstract_factory.example.app;importrefactoring_guru.abstract_factory.example.buttons.Button;importrefactoring_guru.abstract_factory.example.checkboxes.Checkbox;importrefactoring_guru.abstract_factory.example.factories.GUIFactory;/** * Factory users don't care which concrete factory they use since they work with * factories and products through abstract interfaces. */publicclassApplication {privateButton button;privateCheckbox checkbox;publicApplication(GUIFactory factory) { button =factory.createButton(); checkbox =factory.createCheckbox(); }publicvoidpaint() {button.paint();checkbox.paint(); }}
Demo.java: App configuration
packagerefactoring_guru.abstract_factory.example;importrefactoring_guru.abstract_factory.example.app.Application;importrefactoring_guru.abstract_factory.example.factories.GUIFactory;importrefactoring_guru.abstract_factory.example.factories.MacOSFactory;importrefactoring_guru.abstract_factory.example.factories.WindowsFactory;/** * Demo class. Everything comes together here. */publicclassDemo { /** * Application picks the factory type and creates it in run time (usually at * initialization stage), depending on the configuration or environment * variables. */privatestaticApplicationconfigureApplication() {Application app;GUIFactory factory;String osName =System.getProperty("os.name").toLowerCase();if (osName.contains("mac")) { factory =newMacOSFactory(); } else { factory =newWindowsFactory(); } app =newApplication(factory);return app; }publicstaticvoidmain(String[] args) {Application app =configureApplication();app.paint(); }}
OutputDemo.txt: Execution result
You create WindowsButton.
You created WindowsCheckbox.