sbcode.net Open in urlscan Pro
104.131.3.147  Public Scan

Submitted URL: https://sbcode.net/python/factory/#ab
Effective URL: https://sbcode.net/python/factory/
Submission: On April 13 via api from FI — Scanned from FI

Form analysis 1 forms found in the DOM

Name: search

<form class="md-search__form" name="search">
  <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" data-md-state="active" required="">
  <label class="md-search__icon md-icon" for="__search">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M9.5 3A6.5 6.5 0 0116 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 019.5 16 6.5 6.5 0 013 9.5 6.5 6.5 0 019.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"></path>
    </svg>
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"></path>
    </svg>
  </label>
  <button type="reset" class="md-search__icon md-icon" aria-label="Clear" data-md-component="search-reset" tabindex="-1">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"></path>
    </svg>
  </button>
</form>

Text Content

Skip to content

Design Patterns In Python
Factory
Type to start searching
Design Patterns In Python
 * Introduction
 * Environment Setup
 * Coding Conventions
 * UML Diagrams
 * Creational
   Creational
    * Factory Factory
      Table of contents
       * Video Lecture
       * Overview
       * Terminology
       * Factory UML Diagram
       * Source Code
          * ./factory/factory_concept.py
      
       * Output
       * Factory Use Case
       * Factory Example UML Diagram
       * Source Code
          * ./factory/client.py
          * ./factory/interface_chair.py
          * ./factory/chair_factory.py
          * ./factory/small_chair.py
          * ./factory/medium_chair.py
          * ./factory/big_chair.py
      
       * Output
       * New Coding Concepts
          * ABCMeta
      
       * Summary
   
    * Abstract Factory
    * Builder
    * ProtoType
    * Singleton

 * Structural
   Structural
    * Decorator
    * Adapter
    * Facade
    * Bridge
    * Composite
    * Flyweight
    * Proxy

 * Behavioural
   Behavioural
    * Command
    * Chain of Responsibility
    * Observer
    * Interpreter
    * Iterator
    * Mediator
    * Memento
    * State
    * Strategy
    * Template
    * Visitor

 * Summary

Table of contents
 * Video Lecture
 * Overview
 * Terminology
 * Factory UML Diagram
 * Source Code
    * ./factory/factory_concept.py

 * Output
 * Factory Use Case
 * Factory Example UML Diagram
 * Source Code
    * ./factory/client.py
    * ./factory/interface_chair.py
    * ./factory/chair_factory.py
    * ./factory/small_chair.py
    * ./factory/medium_chair.py
    * ./factory/big_chair.py

 * Output
 * New Coding Concepts
    * ABCMeta

 * Summary



Other Tutorials

 Zabbix  Grafana  Prometheus  Threejs and TypeScript  SocketIO and TypeScript
 Blender Topological Earth  Sweet Home 3D  Design Patterns Python
 Design Patterns TypeScript      Course Coupon Codes

Programming Books

Three.js and TypeScript Kindle Edition
$6.99 $9.99 Paperback 
$22.99 $29.99




Design Patterns in TypeScript Kindle Edition
$6.99 $9.99 Paperback
$11.99 $19.99




Design Patterns in Python Kindle Edition
$6.99 $9.99 Paperback
$11.99 $19.99






Special Offer

Zabbix Monitoring Course Discount $11.99
https://www.udemy.com/course/zabbix-monitoring/?couponCode=607976806882D016D221
Offer expires in hours. Be quick and share with your friends and colleagues.

Special Offer

Grafana Course Discount $13.99
https://www.udemy.com/course/grafana-tutorial/?couponCode=D04B41D2EF297CC83032
Offer expires in hours. Be quick and share with your friends and colleagues.

Special Offer

Prometheus Course Discount $9.99
https://www.udemy.com/course/prometheus/?couponCode=EB3123B9535131F1237F
Offer expires in hours. Be quick and share with your friends and colleagues.

Special Offer

Threejs Course Discount $9.99
https://www.udemy.com/course/threejs-tutorials/?couponCode=416F66CD4614B1E0FD02
Offer expires in hours. Be quick and share with your friends and colleagues.


FACTORY DESIGN PATTERN


VIDEO LECTURE

Section Video Links Factory Overview     Factory Use Case     ABCMeta Module    

Your browser does not support the video tag.


OVERVIEW

When developing code, you may instantiate objects directly in methods or in
classes. While this is quite normal, you may want to add an extra abstraction
between the creation of the object and where it is used in your project.

You can use the Factory pattern to add that extra abstraction. The Factory
pattern is one of the easiest patterns to understand and implement.

Adding an extra abstraction will also allow you to dynamically choose classes to
instantiate based on some kind of logic.

Before the abstraction, your client, class or method would directly instantiate
an object of a class. After adding the factory abstraction, the concrete product
(object) is no longer created in the current class/method, but in a subclass
instead.

Imagine an application for designing houses and the house has a chair already
added on the floor by default. By adding the factory pattern, you could give the
option to the user to choose different chairs, and how many at runtime. Instead
of the chair being hard coded into the project when it started, the user now has
the option to choose.

Adding this extra abstraction also means that the complications of instantiating
extra objects can now be hidden from the class or method that is using it.

This separation also makes your code easier to read and document.

The Factory pattern is really about adding that extra abstraction between the
object creation and where it is used. This gives you extra options that you can
more easily extend in the future.


TERMINOLOGY

 * Concrete Creator: The client application, class or method that calls the
   Creator (Factory method).

 * Product Interface: The interface describing the attributes and methods that
   the Factory will require in order to create the final product/object.

 * Creator: The Factory class. Declares the Factory method that will return the
   object requested from it.

 * Concrete Product: The object returned from the Factory. The object implements
   the Product interface.


FACTORY UML DIAGRAM




SOURCE CODE

In this concept example, the client wants an object named b

Rather than creating b directly in the client, it asks the creator (factory) for
the object instead.

The factory finds the relevant class using some kind of logic from the
attributes of the request. It then asks the subclass to instantiate the new
object that it then returns as a reference back to the client asking for it.


./FACTORY/FACTORY_CONCEPT.PY

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

# pylint: disable=too-few-public-methods
# pylint: disable=arguments-differ
"The Factory Concept"
from abc import ABCMeta, abstractmethod

class IProduct(metaclass=ABCMeta):
    "A Hypothetical Class Interface (Product)"

    @staticmethod
    @abstractmethod
    def create_object():
        "An abstract interface method"

class ConcreteProductA(IProduct):
    "A Concrete Class that implements the IProduct interface"

    def __init__(self):
        self.name = "ConcreteProductA"

    def create_object(self):
        return self

class ConcreteProductB(IProduct):
    "A Concrete Class that implements the IProduct interface"

    def __init__(self):
        self.name = "ConcreteProductB"

    def create_object(self):
        return self

class ConcreteProductC(IProduct):
    "A Concrete Class that implements the IProduct interface"

    def __init__(self):
        self.name = "ConcreteProductC"

    def create_object(self):
        return self

class Creator:
    "The Factory Class"

    @staticmethod
    def create_object(some_property):
        "A static method to get a concrete product"
        if some_property == 'a':
            return ConcreteProductA()
        if some_property == 'b':
            return ConcreteProductB()
        if some_property == 'c':
            return ConcreteProductC()
        return None

# The Client
PRODUCT = Creator.create_object('b')
print(PRODUCT.name)



OUTPUT

python ./factory/factory_concept.py
ConcreteProductB



FACTORY USE CASE

An example use case is a user interface where the user can select from a menu of
items, such as chairs.

The user has been given a choice using some kind of navigation interface, and it
is unknown what choice, or how many the user will make until the application is
actually running, and the user starts using it.

So, when the user selected the chair, the factory then takes some property
involved with that selection, such as an ID, Type or other attribute and then
decides which relevant subclass to instantiate in order to return the
appropriate object.


FACTORY EXAMPLE UML DIAGRAM




SOURCE CODE


./FACTORY/CLIENT.PY

1
2
3
4
5
6
7

"Factory Use Case Example Code"

from chair_factory import ChairFactory

# The Client
CHAIR = ChairFactory.get_chair("SmallChair")
print(CHAIR.get_dimensions())



./FACTORY/INTERFACE_CHAIR.PY

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11

# pylint: disable=too-few-public-methods
"The Chair Interface"
from abc import ABCMeta, abstractmethod

class IChair(metaclass=ABCMeta):
    "The Chair Interface (Product)"

    @staticmethod
    @abstractmethod
    def get_dimensions():
        "A static interface method"



./FACTORY/CHAIR_FACTORY.PY

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19

"The Factory Class"

from small_chair import SmallChair
from medium_chair import MediumChair
from big_chair import BigChair

class ChairFactory:  # pylint: disable=too-few-public-methods
    "The Factory Class"

    @staticmethod
    def get_chair(chair):
        "A static method to get a chair"
        if chair == 'BigChair':
            return BigChair()
        if chair == 'MediumChair':
            return MediumChair()
        if chair == 'SmallChair':
            return SmallChair()
        return None



./FACTORY/SMALL_CHAIR.PY

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

# pylint: disable=too-few-public-methods
"A Class of Chair"
from interface_chair import IChair

class SmallChair(IChair):
    "The Small Chair Concrete Class implements the IChair interface"

    def __init__(self):
        self._height = 40
        self._width = 40
        self._depth = 40

    def get_dimensions(self):
        return {
            "width": self._width,
            "depth": self._depth,
            "height": self._height
        }



./FACTORY/MEDIUM_CHAIR.PY

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

# pylint: disable=too-few-public-methods
"A Class of Chair"
from interface_chair import IChair

class MediumChair(IChair):
    "The Medium Chair Concrete Class implements the IChair interface"

    def __init__(self):
        self._height = 60
        self._width = 60
        self._depth = 60

    def get_dimensions(self):
        return {
            "width": self._width,
            "depth": self._depth,
            "height": self._height
        }



./FACTORY/BIG_CHAIR.PY

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

# pylint: disable=too-few-public-methods
"A Class of Chair"
from interface_chair import IChair

class BigChair(IChair):
    "The Big Chair Concrete Class implements the IChair interface"

    def __init__(self):
        self._height = 80
        self._width = 80
        self._depth = 80

    def get_dimensions(self):
        return {
            "width": self._width,
            "depth": self._depth,
            "height": self._height
        }



OUTPUT

python ./factory/client.py
{'width': 40, 'depth': 40, 'height': 40}



NEW CODING CONCEPTS


ABCMETA

ABCMeta classes are a development tool that help you to write classes that
conform to a specified interface that you've designed.

ABCMeta refers to Abstract Base Classes.

The benefits of using ABCMeta classes to create abstract classes is that your
IDE and Pylint will indicate to you at development time whether your inheriting
classes conform to the class definition that you've asked them to.

Abstract interfaces are not instantiated directly in your scripts, but instead
implemented by subclasses that will provide the implementation code for the
abstract interface methods. E.g., you don't create IChair, but you create
SmallChair that implements the methods described in the IChair interface.

An abstract interface method is a method that is declared, but contains no
implementation. The implementation happens at the class that inherits the
abstract class.

You don't need to use ABCMeta classes and interfaces that you have created in
your final Python code. Your code will still work without them.

You can try it by removing the interfaces from all the chair classes above, and
you will see that your Python program will still run.

E.g., change

class BigChair(IChair):


to

class BigChair():


and it will still work.

While it is possible to ensure your classes are correct without using abstract
classes, it is often easier to use abstract classes as a backup method of
checking correctness, especially if your projects become very large and involve
many developers.

Note that in all my code examples, the abstract classes are prefixed with a
capital I, to indicate that they are abstract interfaces. They have no code in
their methods. They do not require a self or cls argument due to the use of
@staticmethod. The inheriting class will implement the code in each of the
methods that the abstract class is describing. If subclasses are inheriting an
abstract base class, and they do not implement the methods as described, there
will be a Pylint error or warning message (E0110).

See PEP 3119 : https://www.python.org/dev/peps/pep-3119/


SUMMARY

 * The Factory Pattern is an Interface that defers the creation of the final
   object to a subclass.
 * The Factory pattern is about inserting another layer/abstraction between
   instantiating an object and where in your code it is actually used.
 * It is unknown what or how many objects will need to be created until runtime.
 * You want to localize knowledge of the specifics of instantiating a particular
   object to the subclass so that the client doesn't need to be concerned about
   the details.
 * You want to create an external framework, that an application can
   import/reference, and hide the details of the specifics involved in creating
   the final object/product.
 * The unique factor that defines the Factory pattern, is that your project now
   defers the creation of objects to the subclass that the factory had delegated
   it to.

Previous UML Diagrams
Next Abstract Factory

Copyright © 2019-2022 Sean Bradley
Made with Material for MkDocs