Description
The Abstract Factory pattern presents an interface for creating a family of products in a way that the client that uses those doesn't know anything about the concrete classes.
Solution offered by the pattern
This pattern is based on the definition of interfaces for every kind of product. There will be concrete classes that implement those interfaces that allow clients to make use of the products. The product families will be created by an object known as factory.
Every family has its particular factory used by the client to create products instances. Because the aim is not to tie the client to a specific factory, these factory implement a common interface known by the client.
Pattern structure
Abstract Factory Design Pattern Structure |
Design pattern application - schema model
Abstract Factory Application - Widgets schema |
Partecipants:
- AbstractFactory: interface WidgetFactory
- declares operations that create and return products.
- the returned products are all AbstractProduct.
- ConcreteFactory: classes WindowsWidgetFactory, LinuxWidgetFactory, MacWidgetFactory.
- implements the AbstractFactory. Creates and returns specific objects correnspondent to specific objects (ConcreteProduct).
- AbstracProduct: interfaces Widget, TextBox, ComboBox, ListBox.
- define the operation that characterize the different generic types of products.
- ConcreteProduct: classes WindowsTextBox, LinuxTextBox, MacTextBox, WindowsComboBox, LinuxComboBox, MacComboBox, WindowsListBox, LinuxListBox, MacListBox.
- define the products created by the ConcreteFactory.
- Client: class Client.
- uses the AbstractFactory to call the ConcreteFactory of a product family.
- uses products by their interface AbstractProduct.
Code Description
Create the interfaces that the classes of every product family will implement. Widget is a marker interface used to identify interface components, while the interfaces TextBox, ComboBox and ListBox define the methods the clients invoke to draw the components.
package com.fa.abstractfactory.product; public interface Widget { }
package com.fa.abstractfactory.product; public interface TextBox extends Widget { public void draw(); }
package com.fa.abstractfactory.product; public interface ListBox extends Widget { public void draw(); }
package com.fa.abstractfactory.product; public interface ComboBox extends Widget { public void draw(); }
We do implement the concrete classes of the products.
package com.fa.abstractfactory.product.impl; import java.util.List; import com.fa.abstractfactory.product.ComboBox; public class LinuxComboBox implements ComboBox{ private ListcomboList; public LinuxComboBox(List list) { System.out.println("LinuxComboBox"); this.comboList = list; } public void draw() { for(int i=0; i < comboList.size(); i++) { System.out.println("- " + comboList.get(i) + " -"); } } }
package com.fa.abstractfactory.product.impl; import java.util.List; import com.fa.abstractfactory.product.ComboBox; public class MacComboBox implements ComboBox { private ListcomboList; public MacComboBox(List list) { System.out.println("MacComboBox"); this.comboList = list; } public void draw() { for(int i=0; i < comboList.size(); i++) { System.out.println("| " + comboList.get(i) + " |"); } } }
package com.fa.abstractfactory.product.impl; import java.util.List; import com.fa.abstractfactory.product.ComboBox; public class WindowsComboBox implements ComboBox { private ListcomboList; public WindowsComboBox(List list) { System.out.println("WindowsComboBox"); this.comboList = list; } public void draw() { for(int i=0; i < comboList.size(); i++) { System.out.println("< " + comboList.get(i) + " >"); } } }
package com.fa.abstractfactory.product.impl; import java.util.List; import com.fa.abstractfactory.product.ListBox; public class LinuxListBox implements ListBox{ private Listlist; public LinuxListBox(List list) { System.out.println("LinuxListBox"); this.list = list; } public void draw() { for(int i=0; i < list.size(); i++) { System.out.println("- " + list.get(i) + " -"); } } }
package com.fa.abstractfactory.product.impl; import java.util.List; import com.fa.abstractfactory.product.ListBox; public class MacListBox implements ListBox{ private Listlist; public MacListBox(List list) { System.out.println("MacListBox"); this.list = list; } public void draw() { for(int i=0; i < list.size(); i++) { System.out.println("| " + list.get(i) + " |"); } } }
package com.fa.abstractfactory.product.impl; import java.util.List; import com.fa.abstractfactory.product.ListBox; public class WindowsListBox implements ListBox { private Listlist; public WindowsListBox(List list) { System.out.println("WindowsListBox"); this.list = list; } public void draw() { for(int i=0; i < list.size(); i++) { System.out.println("< " + list.get(i) + " >"); } } }
package com.fa.abstractfactory.product.impl; import com.fa.abstractfactory.product.TextBox; public class LinuxTextBox implements TextBox { private String text; public LinuxTextBox(String value) { System.out.println("LinuxTextBox"); this.text = value; } public void draw() { System.out.println("- " + text + " -"); } }
package com.fa.abstractfactory.product.impl; import com.fa.abstractfactory.product.TextBox; public class MacTextBox implements TextBox{ private String text; public MacTextBox(String value) { System.out.println("MacTextBox"); this.text = value; } public void draw() { System.out.println("| " + text + " |"); } }
package com.fa.abstractfactory.product.impl; import com.fa.abstractfactory.product.TextBox; public class WindowsTextBox implements TextBox { private String text; public WindowsTextBox(String text) { System.out.println("WindowsTextBox"); this.text = text; } public void draw() { System.out.println("< " + text + " >"); } }
The AbstractFactory interface defines the methods that return the generic type of Products.
package com.fa.abstractfactory.factory; import java.util.List; import com.fa.abstractfactory.product.ComboBox; import com.fa.abstractfactory.product.ListBox; import com.fa.abstractfactory.product.TextBox; public interface WidgetFactory { TextBox createTextBox(String value); ListBox createListBox(Listlist); ComboBox createComboBox(List list); }
Than we define the ConcreteFactory classes that create and return the concrete product for each family
package com.fa.abstractfactory.productfactory; import java.util.List; import com.fa.abstractfactory.factory.WidgetFactory; import com.fa.abstractfactory.product.ComboBox; import com.fa.abstractfactory.product.ListBox; import com.fa.abstractfactory.product.TextBox; import com.fa.abstractfactory.product.impl.LinuxComboBox; import com.fa.abstractfactory.product.impl.LinuxListBox; import com.fa.abstractfactory.product.impl.LinuxTextBox; public class LinuxWidgetFactory implements WidgetFactory{ @Override public TextBox createTextBox(String value) { return new LinuxTextBox(value); } @Override public ListBox createListBox(Listlist) { return new LinuxListBox(list); } @Override public ComboBox createComboBox(List list) { return new LinuxComboBox(list); } }
package com.fa.abstractfactory.productfactory; import java.util.List; import com.fa.abstractfactory.factory.WidgetFactory; import com.fa.abstractfactory.product.ComboBox; import com.fa.abstractfactory.product.ListBox; import com.fa.abstractfactory.product.TextBox; import com.fa.abstractfactory.product.impl.MacComboBox; import com.fa.abstractfactory.product.impl.MacListBox; import com.fa.abstractfactory.product.impl.MacTextBox; public class MacWidgetFactory implements WidgetFactory{ @Override public TextBox createTextBox(String text) { return new MacTextBox(text); } @Override public ListBox createListBox(Listlist) { return new MacListBox(list); } @Override public ComboBox createComboBox(List list) { return new MacComboBox(list); } }
package com.fa.abstractfactory.productfactory; import java.util.List; import com.fa.abstractfactory.factory.WidgetFactory; import com.fa.abstractfactory.product.ComboBox; import com.fa.abstractfactory.product.ListBox; import com.fa.abstractfactory.product.TextBox; import com.fa.abstractfactory.product.impl.WindowsComboBox; import com.fa.abstractfactory.product.impl.WindowsListBox; import com.fa.abstractfactory.product.impl.WindowsTextBox; public class WindowsWidgetFactory implements WidgetFactory{ @Override public TextBox createTextBox(String text) { return new WindowsTextBox(text); } @Override public ListBox createListBox(Listlist) { return new WindowsListBox(list); } @Override public ComboBox createComboBox(List list) { return new WindowsComboBox(list); } }
The Client class defines the objects that every family product uses. Its constructor receives an object correnspondent to a particular family. The test method defines an instance for every particular family product and applies the different methods defined by the interface that the products implement. Note that the Client uses the Products without knowing which concrete object they belong to.
package com.fa.abstractfactory.client; import java.util.Arrays; import java.util.List; import com.fa.abstractfactory.factory.*; import com.fa.abstractfactory.product.impl.MacComboBox; import com.fa.abstractfactory.product.impl.MacListBox; import com.fa.abstractfactory.product.impl.MacTextBox; import com.fa.abstractfactory.productfactory.MacWidgetFactory; public class Client { private WidgetFactory factory; public Client(WidgetFactory factory) { this.factory = factory; } public void test() { factory.createTextBox("Text").draw(); Listlist = Arrays.asList("First", "Second", "Third"); factory.createListBox(list).draw(); factory.createComboBox(list).draw(); } }
Next there is an example class that instantiates 3 Client objects passing to their constructor a family of product:
package com.fa.abstractfactory.test; import com.fa.abstractfactory.client.Client; import com.fa.abstractfactory.productfactory.LinuxWidgetFactory; import com.fa.abstractfactory.productfactory.MacWidgetFactory; import com.fa.abstractfactory.productfactory.WindowsWidgetFactory; public class AbstractFactoryExample { public static void main(String[] args) { Client client1 = new Client(new MacWidgetFactory()); client1.test(); Client client2 = new Client(new LinuxWidgetFactory()); client2.test(); Client client3 = new Client(new WindowsWidgetFactory()); client3.test(); } }
Next image shows you the console output, resulting from launching the previous starter class.
MacTextBox | Text | MacListBox | First | | Second | | Third | MacComboBox | First | | Second | | Third | LinuxTextBox - Text - LinuxListBox - First - - Second - - Third - LinuxComboBox - First - - Second - - Third - WindowsTextBox < Text > WindowsListBox < First > < Second > < Third > WindowsComboBox < First > < Second > < Third >
No comments:
Post a Comment