Safety.  Setup.  Internet.  Recovery.  Installation

Abstract Factory pattern - object level. Factory method - design pattern - description Production of cross-platform GUI elements

Factory method is a generative design pattern that solves the problem of creating different products without specifying specific product classes.

A factory method specifies a method that should be used instead of calling the new operator to create product objects. Subclasses can override this method to change the type of products created.

Features of the pattern in Java

Complexity:

Popularity:

Applicability: The pattern can often be found in any Java code where flexibility is required when creating products.

The pattern is widely used in the Java standard libraries:

  • java.net.URLStreamHandlerFactory#createURLStreamHandler(String) (Returns different singleton objects, depending on the protocol)
  • javax.xml.bind.JAXBContext#createMarshaller() and other similar methods.

Signs of using a pattern: A factory method can be defined by creation methods that return product objects through abstract types or interfaces. This allows you to override the types of products created in subclasses.

Production of cross-platform GUI elements

In this example, the products are buttons and the creator is a dialog.

Different types of dialogs have their own element types. Therefore, for each type of dialogue, we create our own subclass and override the factory method in it.

Each specific dialog will generate the buttons that correspond to it. At the same time, the basic dialog code will not break, since it works with products only through their common interface.

buttons

buttons/Button.java: Common button interface

package site.factory_method.example.buttons; /** * Common interface for all products. */ public interface Button ( void render(); void onClick(); )

buttons/HtmlButton.java: Specific button class

package site.factory_method.example.buttons; /** * Implementation of HTML buttons. */ public class HtmlButton implements Button ( public void render() ( System.out.println(" "); onClick(); ) public void onClick() ( System.out.println("Click! Button says - "Hello World!"); ) )

buttons/WindowsButton.java: Another class of buttons

package site.factory_method.example.buttons; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * Implementation of native operating system buttons. */ public class WindowsButton implements Button ( JPanel panel = new JPanel(); JFrame frame = new JFrame(); JButton button; public void render() ( frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JLabel label = new JLabel("Hello World!"); label.setOpaque(true); label.setBackground(new Color(235, 233, 126)); label.setFont(new Font("Dialog", Font.BOLD, 44)); label.setHorizontalAlignment( SwingConstants.CENTER); panel.setLayout(new FlowLayout(FlowLayout.CENTER)); frame.getContentPane().add(panel); panel.add(label); onClick(); panel.add(button); frame.setSize (320, 200); frame.setVisible(true); onClick(); ) public void onClick() ( button = new JButton("Exit"); button.addActionListener(new ActionListener() ( public void actionPerformed(ActionEvent e) ( frame.setVisible(false); System.exit(0); ) )); ) )

factory

factory/Dialog.java: Basic dialogue

package site.factory_method.example..factory_method.example.buttons.Button; /** * The base class of the factory. Note that "factory" is just * an additional role for the class. It already has some business logic that * requires the creation of a variety of products. */ public abstract class Dialog ( public void renderWindow() ( // ... the rest of the dialog code... Button okButton = createButton(); okButton.render(); ) /** * Subclasses will override this method to create specific * product objects, different for each factory. */ public abstract Button createButton(); )

factory/HtmlDialog.java: Concrete class of dialogues

package site.factory_method.example..factory_method.example.buttons..factory_method.example.buttons.HtmlButton; /** * HTML dialog. */ public class HtmlDialog extends Dialog ( @Override public Button createButton() ( return new HtmlButton(); ) )

factory/WindowsDialog.java: Another class of dialogues

package site.factory_method.example..factory_method.example.buttons..factory_method.example.buttons.WindowsButton; /** * Dialog on operating system elements. */ public class WindowsDialog extends Dialog ( @Override public Button createButton() ( return new WindowsButton(); ) )

Demo.java: Client code

package site.factory_method..factory_method.example.factory..factory_method.example.factory.Html.factory_method.example.factory.WindowsDialog; /** * Demo class. This is where it all comes together. */ public class Demo ( private static Dialog dialog; public static void main(String args) ( configure(); runBusinessLogic(); ) /** * The application creates a specific factory depending on the configuration or * environment. */ static void configure () ( if (System.getProperty("os.name").equals("Windows 10")) ( dialog = new WindowsDialog(); ) else ( dialog = new HtmlDialog(); ) ) /** * Everything else client code interacts with the factory and products only * through a common interface, so it does not matter which factory was * created. */ static void runBusinessLogic() ( dialog.renderWindow(); ) )

OutputDemo.txt: Result with HtmlDialog factory

Click! Button says - "Hello World!"

Description of Factory Method

Factory Method (also known as Virtual Constructor) is a generative design pattern that provides subclasses with an interface for creating instances of a class. At the time of creation, heirs can determine which class to create. In other words, the Factory delegates the creation of objects to the descendants of the parent class. This allows you to use not specific classes in the program code, but manipulate abstract objects at a higher level.

Defines an interface for creating an object, but leaves it to subclasses to decide which class to instantiate. A factory method allows a class to delegate the creation of subclasses. Used when:

  • the class does not know in advance which objects of which subclasses it needs to create.
  • a class is designed so that the objects it creates are specified by subclasses.
  • a class delegates its responsibilities to one of several auxiliary subclasses, and the plan is to localize knowledge of which class assumes these responsibilities

Structure

  • Product- product
    • defines the interface of objects created by an abstract method;
  • ConcreteProduct- specific product
    • implements the interface Product;
  • Creator- creator
    • declares a factory method that returns an object of type Product. May also contain a "default" implementation of this method;
    • can call a factory method to create an object of type Product;
  • ConcreteCreator- specific creator
    • overrides a factory method so that it creates and returns a class object ConcreteProduct.

Factory Method is a creational pattern. This design pattern provides an interface for creating instances of a class. At the time of creation, heirs can determine which class to instantiate.

In other words, the Factory delegates creating objects for descendants of the parent class. This allows you to use not specific classes in the program code, but manipulate abstract objects at a higher level.

The Factory design pattern is very common. Let's look at a small example in Java.

Introduction: Requirements for various kinds of software products are constantly growing. Reports on the execution of application operations should be generated in different forms: XML, HTML, text, etc. This is exactly the case when it is convenient to use the Factory pattern.

Solution: The AbstractWriter class will represent an abstraction for writing to some context (be it an XML document or a text file).

Public abstract class AbstractWriter ( public abstract void write(Object context); )

This class can have any number of descendants. Let's consider the ConcreteFileWriter and ConcreteXmlWriter subclasses for writing to a text file and DOM document, respectively:

Public class ConcreteFileWriter extends AbstractWriter ( public void write (Object context) ( // method body ) ) public class ConcreteXmlWriter extends AbstractWriter ( public void write (Object context) ( // method body ) )

To create the object we need, we can write the following Factory:

Import java.io.File; import org.w3c.dom.Document; public class FactoryMethod ( public AbstractWriter getWriter(Object object) ( AbstractWriter writer = null; if (object instanceof File) ( writer = new ConcreteFileWriter(); ) else if (object instanceof Document) ( writer = new ConcreteXmlWriter(); ) return writer ; ) )

In the text of the program, when creating a report, you need to pass a File object or DOM document to the getWriter function. As a result of executing the method, we will receive the desired object at the required level of abstraction.

Use the Factory pattern in the following cases:

  • the class has no information about what type of object it should create;
  • the class passes responsibility for creating objects to its descendants;
  • you need to create an object depending on the incoming data.

In one of the subsequent design articles we will look at the pattern Abstract Factory.

In the meantime, I will be happy to listen to your questions, remarks and comments.



Comments: 5

As far as I understand, the example (special thanks for the examples in the cycle about patterns) illustrates a parameterized factory, since a parameter is passed to the factory method, on the basis of which a specific AbstractWriter subclass is created. Meanwhile, the classic factory, as far as I understand, behaves somewhat differently: “a class is designed so that the objects it creates are specified by subclasses” (E. Gamma ‘Design Patterns’). That is, there must be several FactoryMethod heirs for each AbstractWriter heir, and the choice remains with the client which FactoryMethod implementation to choose. Did I understand correctly?

In fact, the example does not show the Factory Method at all, but the so-called Simple Factory (this is not even a design pattern, but simply a widely used technique). Danik wrote correctly that the FactoryMethod class must have descendants that actually override the factory method. At first glance it may seem that there is no difference, but the difference is huge. Read “Head First Design Patterns” or “Design Patterns For Dummies” and everything will become clear to you.

You're wrong. This is still a factory method. We read from Erich Gamma: “parameterized factory methods. This is another variation of the pattern that allows the factory method to create different types of products. The factory method is passed a parameter that identifies the type of object being created.

All objects produced by a factory method share a common Product interface. In the documents example, the Application class can support different kinds of documents. You are passing an extra parameter to the CreateDocument method, which determines what type of document needs to be created.”

So before expressing your opinion it would be a good idea to study the mat part

I didn’t understand something, how is this different from the pattern strategy?

Maybe I’m being clever too. antonin yorov The difference between a factory and a strategy is that a strategy allows you to dynamically determine the desired algorithm (that is, you can connect the desired interface subclass in runtime), while a factory has a method in the algorithm that returns an object.

Abstract Factory pattern - object level

Pattern name and classification

An abstract factory is a pattern that generates objects.

Purpose

Provides an interface for creating families of related or interdependent objects without specifying their concrete classes.

Applicability

Using the Abstract Factory pattern is advisable if:

  • the system should not depend on how the objects included in it are created, arranged and presented;
  • related objects in a family must be used together, and you must enforce this restriction;
  • the system must be configured by one of the families of its constituent objects;
  • you want to expose a library of objects, exposing only their interfaces, not their implementation.

Let us give examples of groups of interconnected objects.

Let some application with support for a graphical user interface be designed for use on various platforms, and the appearance of this interface must correspond to the accepted style for a particular platform. For example, if this application is installed on a Windows platform, then its buttons, menus, and scroll bars should be displayed in the style adopted for Windows. The group of interrelated objects in this case will be the elements of the graphical user interface for a specific platform.

Another example. Let's consider a text editor with multilingual support, which has functional modules responsible for hyphenation and spell checking. If a document is opened in Russian, then the appropriate modules must be connected, taking into account the specifics of the Russian language. The situation when for such a document the hyphenation module for the Russian language and the spell checking module for the German language are simultaneously used is excluded. Here, a group of interrelated objects will be corresponding modules that take into account the specifics of a certain language.

And one last example. Above we talked about the strategy game “Punic Wars”. Obviously, the appearance, battle formations and characteristics for different types of troops (infantry, archers, cavalry) in each army will be different. In this case, the family of interconnected objects will be all types of warriors for one or another warring side, while, for example, such a situation should be excluded when the Roman cavalry fights on the side of Carthage.

Structure

The structure of the Abstract Factory pattern is shown in Fig. 35.

Rice. 35.

Participants

AbstractFactory - abstract factory: declares an interface for operations that create abstract product objects.

ConcreteFactory (ConcreteFactoryl, ConcreteFactory2) - a concrete factory: implements operations that create specific product objects (for the game “Punic Wars” the armies of Rome and Carthage are created).

AbstractProduct (Abstract Product A, Abstract Product B) - abstract product: declares an interface for a product object type.

ConcreteProduct (ProductA, Product B) - concrete product: defines a product object created by the corresponding concrete factory (for example, archer, horseman) - implements the Abstract Product interface.

Client - client: uses exclusively the interfaces that are declared in the AbstractFactory and AbstractProduct classes.

Relationship

Typically, a single instance of the ConcreteFactory class is created at runtime. This particular factory creates product objects that have a very specific implementation. To create other types of objects, the client must use a different specific factory.

Abstract Factory delegates the creation of product objects to its ConcreteFactory subclass.

results

The Abstract Factory pattern has the following pros and cons:

  • isolates concrete classes. Helps control the classes of objects created by the application. Because a factory encapsulates the responsibility for creating classes and the process of creating them, it isolates the client from the implementation details of the classes. Clients manipulate instances through their abstract interfaces. The names of the classes produced are known only to the specific factory; they are not mentioned in the client code;
  • simplifies the replacement of product families. A specific factory class appears in an application only once: when instantiated. This makes it easier to change which specific factory an application uses. The application can change the configuration of products simply by substituting a new specific factory. Since the abstract factory creates the entire family of products, the entire family is replaced at once. In our UI example, moving from Motif widgets to Presentation Manager widgets is as simple as switching to the appropriate factory products and re-creating the interface;
  • guarantees product compatibility. If products of a certain family are designed to be used together, then it is important that the application only works with products of a single family at any time. The Abstract Factory class makes it easy to meet this constraint;
  • It is difficult to support a new type of product. Expanding an abstract factory to make new types of products is no easy task. The Abstract Factory interface captures the set of products that can be created. To support new products, it is necessary to extend the factory interface, that is, change the AbstractFactory class and all its subclasses.

Example code for the Abstract Factory pattern

Here is an implementation of the Abstract Factory pattern for the military strategy “Punic Wars”. It is assumed that the number and types of combat units created in the game are identical for both armies. Each army consists of infantrymen (Infantryman), archers (Archer) and cavalry (Horseman).

The structure of the pattern for this case is shown in Fig. 36.

ArmyFactory

infantryman

Roman Infantryman

Carthaginianlnfantryman

InfantrymanO

Archer()

Horseman About

- Carthaginian ArmyFactory

Roman ArmyFactory

Carthaginianlnfantryman()

CarthaginianArcher()

CarthaginianHorseman()

RomanInfantryman()

- -> Roman Archer

Archer

Carthaginian Archer

CarthaginianHorscnian

Rice. 36. UML class diagram for the military strategy “Punic Wars”

// Abstract base classes of all possible types of warriors class Infantryman

virtual void info() = 0; virtual ~Infantryman() ()

virtual void info() = 0; virtual ~Archer()()

virtual void info() = 0; virtual ~Horseman() ()

// Classes of all types of warriors of the Roman army class Romanlnfantryman: public Infantryman (

public: void info() (

class RomanArcher: public Archer

public: void info() (

class RomanHorseman: public Horseman

public: void info() (

// Classes of all types of warriors in the Carthaginian army class Carthaginianlnfantryman: public Infantryman

public: void info() (

class CarthaginianArcher: public Archer

public: void info() (

class CarthaginianHorseman: public Horseman

public: void info() (

//Abstract factory for the production of warriors class ArmyFactory (

virtual Infantryman* createlnfantryman() = 0; virtual Archer* createArcher() = 0; virtual Horseman* createHorseman() = 0; virtual ~ArmyFactory() ()

// Factory for creating soldiers of the Roman army class RomanArmyFactory: public ArmyFactory (

Infantryman* createlnfantryman() ( return new Romanlnfantryman;

Archer* createArcher() ( return new RomanArcher;

Horseman* createHorseman() ( return new RomanHorseman;

// Factory for creating soldiers of the Carthaginian army class CarthaginianArmyFactory: public ArmyFactory (

Infantryman* createlnfantryman() ( return new Carthaginianlnfantryman;

Archer* createArcherQ ( return new CarthaginianArcher;

Horseman* createHorsemanQ ( return new Carthaginian Horseman;

~Army() ( int i;

void info() ( int i;

for(i=0; i info(); for(i=0; i info(); for(i=0; i info();

vector vi; vector va; vector vh;

// Here an army of one side or another is created class Game

Army* createArmy(ArmyFactory& factory) ( Army* p = new Army;

p->vi.push_back(factory.createInfantryman()); p->va.push_back(factory.createArcher()); p->vh.push_back(factory.createHorseman()); return p;

RomanArmyFactory ra_factory; CarthaginianArmyFactory ca_factory;

Army * ga = game.createArmy(ra_factory);

Army * ca = game.createArmy(ca_factory); co?t info();

The output of the program will be as follows:

Roman Infantryman

Carthaginian army:

Carthaginianlnfantryman

Carthaginian Archer

Carthaginian Horseman

Advantages of the Abstract Factory pattern

Hides the process of generating objects itself, and also makes the system independent of the types of objects being created, specific to various families or groups (users operate these objects through the corresponding abstract interfaces).

Allows you to quickly configure the system for the desired family of created objects. In the case of a multi-platform graphical application, to migrate to a new platform, i.e., to replace graphical elements (buttons, menus, scroll bars) of one style with another, it is enough to create the necessary subclass of the abstract factory. In this case, the condition that it is impossible to simultaneously use elements of different styles for a certain platform will be fulfilled automatically.

Disadvantages of the Abstract Factory Pattern

It is difficult to add new types of created products or replace existing ones because the interface of the abstract factory base class is fixed. For example, if for our strategic game we need to introduce a new type of military unit - siege weapons, then we will need to add a new factory method, declaring its interface in the polymorphic base class AbstractFactory and implementing it in all subclasses. You can remove this restriction as follows. All created objects must inherit from a common abstract base class, and the type identifier of the object to be created must be passed as a parameter to a single factory method. However, in this case the following point must be taken into account. A factory method creates an object of the requested subclass, but returns it with a generic abstract class interface as a reference or pointer, so it would be difficult for such an object to perform any subclass-specific operation.

Related patterns

Abstract Factory classes are often implemented using factory methods (the Factory Method pattern), but can also be implemented using the Prototype pattern. A specific factory can be described by the Singleton pattern.

Factory Method pattern - class level

Pattern name and classification

A factory method is a pattern that generates classes.

Purpose

Defines an interface for creating an object, but leaves it to subclasses to decide which class to instantiate. A factory method allows a class to delegate instantiation to subclasses.

Also known as Virtual Constructor.

Applicability of the Factory Method pattern

The system often needs to create objects of many different types. The Factory Method pattern can be useful if the system needs to remain extensible by adding new types of objects. Using an Expression Directly new is undesirable, since in this case the code for creating objects indicating specific types may end up scattered throughout the application. Then operations such as adding new types of objects to the system or replacing objects of one type with another will be difficult. Pattern Factory Method allows the system to remain independent both from the process of generating objects and from their types.

  • 1. It is known in advance when an object needs to be created, but its type is unknown.
  • 2. A class is designed so that the objects it creates are specified by subclasses.
  • 3. A class delegates its responsibilities to one of several supporting subclasses, and you plan to localize the knowledge of which class takes over those responsibilities.

Description of the Factory Method pattern

In order for the system to remain independent of different types of objects, the Factory Method pattern uses a mechanism polymorphism- classes of all final types inherit from one abstract base class intended for polymorphic use. This base class defines a single interface through which the user will operate objects of final types.

To make it relatively easy to add new types to the system, the Factory Method pattern localizes the creation of objects of specific types in a special factory class. The methods of this class, through which objects of specific classes are created, are called factory methods.

Structure

There are two varieties of the Factory Method pattern.

A generic constructor is when a static factory method is defined in the same polymorphic base class from which derived classes of all types created in the system inherit. The type identifier of the object being created must be passed as a parameter to this method (Fig. 32).

The classic version of the factory method, when the interface of factory methods is declared in an independent factory class, and their implementation is determined by specific subclasses of this class(Fig. 33).

Subclasses of a class Creator override an abstract operation Factory Method in such a way that it returns a suitable

Rice. 32.

Generic constructor

Rice. 33.

Classic implementation

return newConcreteProduct

class class Concrete Product. Once the subclass Creator will instantiated, it can instantiate application-specific documents without knowing anything about their classes. Operation Factory Method called factory method since it is responsible for the “making” of the object.

Participants

Product (product) - defines the interface of objects created by the factory method.

ConcreteProduct (concrete product) - implements the Product interface.

Creator - declares a factory method that returns an object of type Product. The Creator can also define a default implementation of a factory method that returns a ConcreteProduct object.

Can call a factory method to create a Product object.

ConcreteCreator - Overrides a factory method that returns a ConcreteProduct object.

Relationship

The creator "relies" on its subclasses to define a factory method that will return an instance of the appropriate specific product.

results

Factory methods eliminate the need for the designer to build application-specific classes into the code. The code deals only with the Product class interface, so it can work with any user-defined concrete product classes.

A potential disadvantage of the factory method is that clients may have to subclass Creator to create just one ConcreteProduct object. Subclassing is justified if the client has to subclass the Creator anyway, otherwise the client will have to deal with an additional layer of subclassing.

Example code

Let's consider both options for implementing the Factory Method pattern using the example of the process of generating military characters for the strategy game described earlier. To simplify the demo code, we will create military characters for some abstract army without taking into account the characteristics of the warring parties.

Implementation of the Factory Method pattern based on a generic constructor

enum Warrior_ID (Infantryman_ID=0, Archer_ID, Horseman_ID );

// Hierarchy of game character classes class Warrior (

// Parameterized static factory method static Warrior* createWarrior(Warrior_ID id);

public: void info() (

class Archer: public Warrior

public: void info() (

public: void info() (

// Implementation of a parameterized factory method Warrior* Warrior::createWarrior(Warrior_ID id)

Warrior*p; switch (id)

case Infantryman_ID: p = new Infantryman(); break;

case Archer_ID: p = new Archer(); break;

case Horseman ID: p = new Horseman(); break;

default: assert(false);

// Create objects using a parameterized factory

v.push_back(Warrior: :createWarrior(Infantryman_ID));

v.push_back(Warrior::createWarrior(Archer_ID));

v.push_back(Warrior::createWarrior(Horseman_ID));

for(int i=0; i info();

Presented version of the pattern Factory Method is popular due to its simplicity. In it, the static factory method createWarrior() is defined directly in the polymorphic Warrior base class. This factory method is parameterized, i.e., to create an object of a certain type, the corresponding type identifier is passed to createWarriorQ.

From the point of view of the “purity” of object-oriented code, this option has the following disadvantages:

  • since the code for creating objects of all possible types is concentrated in the static factory method of the class Warrior, then the base class Warrior has knowledge of all classes derived from it, which is atypical for an object-oriented approach;
  • similar use of operator switch(as in factory method code createWarrior()) It is also not welcome in object-oriented programming.

These disadvantages are absent in the classic implementation of the Factory Method pattern.

Classic implementation of the Factory Method pattern

// Hierarchy of game character classes

virtual void info() = 0; virtual ~Warrior() ()

class Infantryman: public Warrior

public: void info() (

class Archer: public Warrior

public: void info() (

class Horseman: public Warrior

public: void info() (

// Object factories class Factory

virtual Warrior* createWarrior() = 0; virtual ~Factory() ()

class Infantry Factory: public Factory

Warrior* createWarrior() ( return new Infantryman;

class ArchersFactory: public Factory

Warrior* createWarrior() ( return new Archer;

class CavalryFactory: public Factory

Warrior* createWarrior() ( return new Horseman;

// Creating objects using object factories int main()

InfantryFactory* infantry_factory = new Infantry Factory; ArchersFactory* archers_factory = new ArchersFactory ; CavalryFactory* cavalry_factory = new CavalryFactory ;

v.push_back(infantry_factory->createWarrior()); v.push_back(archers_factory->createWarrior()); v.push_back(cavalry_factory->createWarrior());

for(int i=0; i info();

The classic version of the Factory Method pattern uses the idea of ​​a polymorphic factory. The polymorphic base class Factory, specially dedicated to creating objects, declares the interface of the createWarrior() factory method, and derived classes implement it.

The presented version of the Factory Method pattern is the most common, but not the only one. The following variations are possible:

  • 1) the Factory class has a factory method implementation createWarrior() default;
  • 2) factory method createVamor() the Factory class is parameterized by the type of the object being created (as with the simple version presented earlier Factory Method and has a default implementation. In this case, Factory-derived classes are needed only to define non-standard behavior createWarrior().

Advantages of the Factory Method pattern

Creates objects of different types, allowing the system to remain independent both from the creation process itself and from the types of objects being created.

Disadvantages of the Factory Method pattern

In the case of the classic version of the pattern, even to generate a single object, it is necessary to create a corresponding factory.

Related patterns

Abstract factory often implemented using Factory methods.

Factory method pattern often called internally Template methods.