The abstract factory pattern in software engineering is a design pattern that provides a way to create families of related objects without imposing their concrete classes, by encapsulating a group of individual factories that have a common theme without specifying their concrete classes. [1] According to this pattern, a client software component creates a concrete implementation of the abstract factory and then uses the generic interface of the factory to create the concrete objects that are part of the family. The client does not know which concrete objects it receives from each of these internal factories, as it uses only the generic interfaces of their products. [1] This pattern separates the details of implementation of a set of objects from their general usage and relies on object composition, as object creation is implemented in methods exposed in the factory interface. [2]
Use of this pattern enables interchangeable concrete implementations without changing the code that uses them, even at runtime. However, employment of this pattern, as with similar design patterns, may result in unnecessary complexity and extra work in the initial writing of code. Additionally, higher levels of separation and abstraction can result in systems that are more difficult to debug and maintain.
The abstract factory design pattern is one of the 23 patterns described in the 1994 Design Patterns book. It may be used to solve problems such as: [3]
Creating objects directly within the class that requires the objects is inflexible. Doing so commits the class to particular objects and makes it impossible to change the instantiation later without changing the class. It prevents the class from being reusable if other objects are required, and it makes the class difficult to test because real objects cannot be replaced with mock objects.
A factory is the location of a concrete class in the code at which objects are constructed. Implementation of the pattern intends to insulate the creation of objects from their usage and to create families of related objects without depending on their concrete classes. [2] This allows for new derived types to be introduced with no change to the code that uses the base class.
The pattern describes how to solve such problems:
This makes a class independent of how its objects are created. A class may be configured with a factory object, which it uses to create objects, and the factory object can be exchanged at runtime.
Design Patterns describes the abstract factory pattern as "an interface for creating families of related or dependent objects without specifying their concrete classes." [4]
The factory determines the concrete type of object to be created, and it is here that the object is actually created. However, the factory only returns a reference (in Java, for instance, by the new operator) or a pointer of an abstract type to the created concrete object.
This insulates client code from object creation by having clients request that a factory object create an object of the desired abstract type and return an abstract pointer to the object. [5]
An example is an abstract factory class DocumentCreator
that provides interfaces to create a number of products (e.g., createLetter()
and createResume()
). The system would have any number of derived concrete versions of the DocumentCreator
class such asFancyDocumentCreator
or ModernDocumentCreator
, each with a different implementation of createLetter()
and createResume()
that would create corresponding objects such asFancyLetter
or ModernResume
. Each of these products is derived from a simple abstract class such asLetter
or Resume
of which the client is aware. The client code would acquire an appropriate instance of the DocumentCreator
and call its factory methods. Each of the resulting objects would be created from the same DocumentCreator
implementation and would share a common theme. The client would only need to know how to handle the abstract Letter
or Resume
class, not the specific version that was created by the concrete factory.
As the factory only returns a reference or a pointer to an abstract type, the client code that requested the object from the factory is not aware of—and is not burdened by—the actual concrete type of the object that was created. However, the abstract factory knows the type of a concrete object (and hence a concrete factory). For instance, the factory may read the object's type from a configuration file. The client has no need to specify the type, as the type has already been specified in the configuration file. In particular, this means:
In the above UML class diagram, the Client
class that requires ProductA
and ProductB
objects does not instantiate the ProductA1
and ProductB1
classes directly. Instead, the Client
refers to the AbstractFactory
interface for creating objects, which makes the Client
independent of how the objects are created (which concrete classes are instantiated). The Factory1
class implements the AbstractFactory
interface by instantiating the ProductA1
and ProductB1
classes.
The UML sequence diagram shows the runtime interactions. The Client
object calls createProductA()
on the Factory1
object, which creates and returns a ProductA1
object. Thereafter, the Client
calls createProductB()
on Factory1
, which creates and returns a ProductB1
object.
The original structure of the abstract factory pattern, as defined in 1994 in Design Patterns , is based on abstract classes for the abstract factory and the abstract products to be created. The concrete factories and products are classes that specialize the abstract classes using inheritance. [4]
A more recent structure of the pattern is based on interfaces that define the abstract factory and the abstract products to be created. This design uses native support for interfaces or protocols in mainstream programming languages to avoid inheritance. In this case, the concrete factories and products are classes that realize the interface by implementing it. [1]
This C++11 implementation is based on the pre C++98 implementation in the book.
#include<iostream>enumDirection{North,South,East,West};classMapSite{public:virtualvoidenter()=0;virtual~MapSite()=default;};classRoom:publicMapSite{public:Room():roomNumber(0){}Room(intn):roomNumber(n){}voidsetSide(Directiond,MapSite*ms){std::cout<<"Room::setSide "<<d<<' '<<ms<<'\n';}virtualvoidenter(){}Room(constRoom&)=delete;// rule of threeRoom&operator=(constRoom&)=delete;private:introomNumber;};classWall:publicMapSite{public:Wall(){}virtualvoidenter(){}};classDoor:publicMapSite{public:Door(Room*r1=nullptr,Room*r2=nullptr):room1(r1),room2(r2){}virtualvoidenter(){}Door(constDoor&)=delete;// rule of threeDoor&operator=(constDoor&)=delete;private:Room*room1;Room*room2;};classMaze{public:voidaddRoom(Room*r){std::cout<<"Maze::addRoom "<<r<<'\n';}Room*roomNo(int)const{returnnullptr;}};classMazeFactory{public:MazeFactory()=default;virtual~MazeFactory()=default;virtualMaze*makeMaze()const{returnnewMaze;}virtualWall*makeWall()const{returnnewWall;}virtualRoom*makeRoom(intn)const{returnnewRoom(n);}virtualDoor*makeDoor(Room*r1,Room*r2)const{returnnewDoor(r1,r2);}};// If createMaze is passed an object as a parameter to use to create rooms, walls, and doors, then you can change the classes of rooms, walls, and doors by passing a different parameter. This is an example of the Abstract Factory (99) pattern.classMazeGame{public:Maze*createMaze(MazeFactory&factory){Maze*aMaze=factory.makeMaze();Room*r1=factory.makeRoom(1);Room*r2=factory.makeRoom(2);Door*aDoor=factory.makeDoor(r1,r2);aMaze->addRoom(r1);aMaze->addRoom(r2);r1->setSide(North,factory.makeWall());r1->setSide(East,aDoor);r1->setSide(South,factory.makeWall());r1->setSide(West,factory.makeWall());r2->setSide(North,factory.makeWall());r2->setSide(East,factory.makeWall());r2->setSide(South,factory.makeWall());r2->setSide(West,aDoor);returnaMaze;}};intmain(){MazeGamegame;MazeFactoryfactory;game.createMaze(factory);}
The program output is:
Maze::addRoom0x1317ed0Maze::addRoom0x1317ef0Room::setSide00x1318340Room::setSide20x1317f10Room::setSide10x1318360Room::setSide30x1318380Room::setSide00x13183a0Room::setSide20x13183c0Room::setSide10x13183e0Room::setSide30x1317f10
In object-oriented programming, a class is an extensible program-code-template for creating objects, providing initial values for state and implementations of behavior.
Design Patterns: Elements of Reusable Object-Oriented Software (1994) is a software engineering book describing software design patterns. The book was written by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, with a foreword by Grady Booch. The book is divided into two parts, with the first two chapters exploring the capabilities and pitfalls of object-oriented programming, and the remaining chapters describing 23 classic software design patterns. The book includes examples in C++ and Smalltalk.
The bridge pattern is a design pattern used in software engineering that is meant to "decouple an abstraction from its implementation so that the two can vary independently", introduced by the Gang of Four. The bridge uses encapsulation, aggregation, and can use inheritance to separate responsibilities into different classes.
In computer programming, the flyweight software design pattern refers to an object that minimizes memory usage by sharing some of its data with other similar objects. The flyweight pattern is one of twenty-three well-known GoF design patterns. These patterns promote flexible object-oriented software design, which is easier to implement, change, test, and reuse.
The builder pattern is a design pattern designed to provide a flexible solution to various object creation problems in object-oriented programming. The intent of the builder design pattern is to separate the construction of a complex object from its representation. It is one of the Gang of Four design patterns.
In object oriented programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.
The prototype pattern is a creational design pattern in software development. It is used when the types of objects to create is determined by a prototypical instance, which is cloned to produce new objects. This pattern is used to avoid subclasses of an object creator in the client application, like the factory method pattern does, and to avoid the inherent cost of creating a new object in the standard way when it is prohibitively expensive for a given application.
In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes a group of objects that are treated the same way as a single instance of the same type of object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.
In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other instances of the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern as well as to the Open-Closed Principle, by allowing the functionality of a class to be extended without being modified. Decorator use can be more efficient than subclassing, because an object's behavior can be augmented without defining an entirely new object.
In computer programming, the interpreter pattern is a design pattern that specifies how to evaluate sentences in a language. The basic idea is to have a class for each symbol in a specialized computer language. The syntax tree of a sentence in the language is an instance of the composite pattern and is used to evaluate (interpret) the sentence for a client. See also Composite pattern.
In software design and engineering, the observer pattern is a software design pattern in which an object, named the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
A method in object-oriented programming (OOP) is a procedure associated with an object, and generally also a message. An object consists of state data and behavior; these compose an interface, which specifies how the object may be used. A method is a behavior of an object parametrized by a user.
In object-oriented programming such as is often used in C++ and Object Pascal, a virtual function or virtual method is an inheritable and overridable function or method that is dispatched dynamically. Virtual functions are an important part of (runtime) polymorphism in object-oriented programming (OOP). They allow for the execution of target functions that were not precisely identified at compile time.
In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or in added complexity to the design due to inflexibility in the creation procedures. Creational design patterns solve this problem by somehow controlling this object creation.
In software engineering, dependency injection is a programming technique in which an object or function receives other objects or functions that it requires, as opposed to creating them internally. Dependency injection aims to separate the concerns of constructing objects and using them, leading to loosely coupled programs. The pattern ensures that an object or function which wants to use a given service should not have to know how to construct those services. Instead, the receiving 'client' is provided with its dependencies by external code, which it is not aware of. Dependency injection makes implicit dependencies explicit and helps solve the following problems:
In object-oriented programming, a factory is an object for creating other objects; formally, it is a function or method that returns objects of a varying prototype or class from some method call, which is assumed to be "new". More broadly, a subroutine that returns a "new" object may be referred to as a "factory", as in factory method or factory function. The factory pattern is the basis for a number of related software design patterns.
In object-oriented design, the dependency inversion principle is a specific methodology for loosely coupled software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are reversed, thus rendering high-level modules independent of the low-level module implementation details. The principle states:
In programming languages, an abstract type is a type in a nominative type system that cannot be instantiated directly; by contrast, a concrete typecan be instantiated directly. Instantiation of an abstract type can occur only indirectly, via a concrete subtype.
The curiously recurring template pattern (CRTP) is an idiom, originally in C++, in which a class X
derives from a class template instantiation using X
itself as a template argument. More generally it is known as F-bound polymorphism, and it is a form of F-bounded quantification.
In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral (null) behavior. The null object design pattern, which describes the uses of such objects and their behavior, was first published as "Void Value" and later in the Pattern Languages of Program Design book series as "Null Object".
Object Creational: Abstract Factory: Intent: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
{{cite web}}
: CS1 maint: bot: original URL status unknown (link)The factory insulates the client from changes to the product or how it is created, and it can provide this insulation across objects derived from very different abstract interfaces.
{{cite web}}
: CS1 maint: bot: original URL status unknown (link)