mirror of
https://github.com/rjNemo/design-patterns
synced 2026-06-06 02:26:40 +00:00
chore: enforce style guidelines
This commit is contained in:
parent
d525eb96b1
commit
6b031eb853
13 changed files with 48 additions and 40 deletions
|
|
@ -8,10 +8,10 @@ class AbstractFactory(ABC):
|
|||
"""
|
||||
The Abstract Factory interface declares a set of methods that return
|
||||
different abstract products. These products are called a family and are
|
||||
related by a high-level theme or concept. Products of one family are usually
|
||||
able to collaborate among themselves. A family of products may have several
|
||||
variants, but the products of one variant are incompatible with products of
|
||||
another.
|
||||
related by a high-level theme or concept. Products of one family are
|
||||
usually able to collaborate among themselves. A family of products may have
|
||||
several variants, but the products of one variant are incompatible with
|
||||
products of another.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from abc import ABC
|
||||
|
||||
|
||||
class AbstractProductA(ABC):
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ from AbstractProductA import AbstractProductA
|
|||
class AbstractProductB(ABC):
|
||||
"""
|
||||
Here's the the base interface of another product. All products can interact
|
||||
with each other, but proper interaction is possible only between products of
|
||||
the same concrete variant.
|
||||
with each other, but proper interaction is possible only between products
|
||||
of the same concrete variant.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
from AbstractFactory import AbstractFactory
|
||||
from products import (ConcreteProductA1, ConcreteProductA2, ConcreteProductB1,
|
||||
ConcreteProductB2)
|
||||
from products import (
|
||||
ConcreteProductA1,
|
||||
ConcreteProductA2,
|
||||
ConcreteProductB1,
|
||||
ConcreteProductB2,
|
||||
)
|
||||
|
||||
|
||||
class ConcreteFactory1(AbstractFactory):
|
||||
"""
|
||||
Concrete Factories produce a family of products that belong to a single
|
||||
variant. The factory guarantees that resulting products are compatible. Note
|
||||
that signatures of the Concrete Factory's methods return an abstract
|
||||
variant. The factory guarantees that resulting products are compatible.
|
||||
Note that signatures of the Concrete Factory's methods return an abstract
|
||||
product, while inside the method a concrete product is instantiated.
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -15,15 +15,14 @@ class ConcreteProductA2(AbstractProductA):
|
|||
|
||||
|
||||
class ConcreteProductB1(AbstractProductB):
|
||||
|
||||
def useful_function_b(self) -> str:
|
||||
return "The result of the product B1."
|
||||
|
||||
def another_useful_function_b(self, collaborator: AbstractProductA) -> str:
|
||||
"""
|
||||
The variant, Product B1, is only able to work correctly with the variant,
|
||||
Product A1. Nevertheless, it accepts any instance of AbstractProductA as an
|
||||
argument.
|
||||
The variant, Product B1, is only able to work correctly with the
|
||||
variant, Product A1. Nevertheless, it accepts any instance of
|
||||
AbstractProductA as an argument.
|
||||
"""
|
||||
result = collaborator.useful_function_a()
|
||||
return f"The result of the B1 collaborating with the ({result})"
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@ class Director:
|
|||
@builder.setter
|
||||
def builder(self, builder: Builder) -> None:
|
||||
"""
|
||||
The Director works with any builder instance that the client code passes
|
||||
to it. This way, the client code may alter the final type of the newly
|
||||
assembled product.
|
||||
The Director works with any builder instance that the client code
|
||||
passes to it. This way, the client code may alter the final type of the
|
||||
newly assembled product.
|
||||
"""
|
||||
self._builder = builder
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ class ConcreteBuilder1(Builder):
|
|||
|
||||
def __init__(self) -> None:
|
||||
"""
|
||||
A fresh builder instance should contain a blank product object, which is
|
||||
used in further assembly.
|
||||
A fresh builder instance should contain a blank product object, which
|
||||
is used in further assembly.
|
||||
"""
|
||||
self.reset()
|
||||
|
||||
|
|
@ -25,8 +25,8 @@ class ConcreteBuilder1(Builder):
|
|||
Concrete Builders are supposed to provide their own methods for
|
||||
retrieving results. That's because various types of builders may create
|
||||
entirely different products that don't follow the same interface.
|
||||
Therefore, such methods cannot be declared in the base Builder interface
|
||||
(at least in a statically typed programming language).
|
||||
Therefore, such methods cannot be declared in the base Builder
|
||||
interface (at least in a statically typed programming language).
|
||||
|
||||
Usually, after returning the end result to the client, a builder
|
||||
instance is expected to be ready to start producing another product.
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ class Product1:
|
|||
It makes sense to use the Builder pattern only when your products are quite
|
||||
complex and require extensive configuration.
|
||||
|
||||
Unlike in other creational patterns, different concrete builders can produce
|
||||
unrelated products. In other words, results of various builders may not
|
||||
always follow the same interface.
|
||||
Unlike in other creational patterns, different concrete builders can
|
||||
produce unrelated products. In other words, results of various builders may
|
||||
not always follow the same interface.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ class ICreator(ABC):
|
|||
product = self.factory_method()
|
||||
|
||||
# Now, use the product.
|
||||
result = f"Creator: The same creator's code has just worked with {product.operation()}"
|
||||
result = f"""
|
||||
Creator: The same creator's code has just worked with
|
||||
{product.operation()}
|
||||
"""
|
||||
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -21,6 +21,5 @@ class ConcreteCreator1(ICreator):
|
|||
|
||||
|
||||
class ConcreteCreator2(ICreator):
|
||||
|
||||
def factory_method(self) -> ConcreteProduct2:
|
||||
return ConcreteProduct2()
|
||||
|
|
|
|||
|
|
@ -4,13 +4,16 @@ from ICreator import ICreator
|
|||
|
||||
def client_code(creator: ICreator) -> None:
|
||||
"""
|
||||
The client code works with an instance of a concrete creator, albeit through
|
||||
its base interface. As long as the client keeps working with the creator via
|
||||
the base interface, you can pass it any creator's subclass.
|
||||
The client code works with an instance of a concrete creator, albeit
|
||||
through its base interface. As long as the client keeps working with the
|
||||
creator via the base interface, you can pass it any creator's subclass.
|
||||
"""
|
||||
|
||||
print(f"Client: I'm not aware of the creator's class, but it still works.\n"
|
||||
f"{creator.some_operation()}", end="")
|
||||
print(
|
||||
f"Client: I'm not aware of the creator's class, but it still works.\n"
|
||||
f"{creator.some_operation()}",
|
||||
end="",
|
||||
)
|
||||
|
||||
|
||||
print("App: Launched with the ConcreteCreator1.")
|
||||
|
|
|
|||
|
|
@ -21,15 +21,16 @@ class SomeComponent:
|
|||
implementations have to override `__copy__` and `__deepcopy__` member
|
||||
functions.
|
||||
"""
|
||||
|
||||
some_int: int
|
||||
some_list_of_objects: List
|
||||
some_circular_ref: Any
|
||||
|
||||
def __copy__(self) -> SomeComponent:
|
||||
"""
|
||||
Create a shallow copy. This method will be called whenever someone calls
|
||||
`copy.copy` with this object and the returned value is returned as the
|
||||
new shallow copy.
|
||||
Create a shallow copy. This method will be called whenever someone
|
||||
calls `copy.copy` with this object and the returned value is returned
|
||||
as the new shallow copy.
|
||||
"""
|
||||
|
||||
# First, let's create copies of the nested objects.
|
||||
|
|
@ -38,8 +39,7 @@ class SomeComponent:
|
|||
|
||||
# Then, let's clone the object itself, using the prepared clones of the
|
||||
# nested objects.
|
||||
new = self.__class__(
|
||||
self.some_int, some_list_of_objects, some_circular_ref)
|
||||
new = self.__class__(self.some_int, some_list_of_objects, some_circular_ref)
|
||||
new.__dict__.update(self.__dict__)
|
||||
|
||||
return new
|
||||
|
|
@ -63,8 +63,7 @@ class SomeComponent:
|
|||
|
||||
# Then, let's clone the object itself, using the prepared clones of the
|
||||
# nested objects.
|
||||
new = self.__class__(
|
||||
self.some_int, some_list_of_objects, some_circular_ref)
|
||||
new = self.__class__(self.some_int, some_list_of_objects, some_circular_ref)
|
||||
|
||||
new.__dict__ = copy.deepcopy(self.__dict__, memo)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ circular_ref.set_parent(component)
|
|||
|
||||
shallow_copied_component = copy.copy(component)
|
||||
|
||||
# Let's change the list in shallow_copied_component and see if it changes in component.
|
||||
# Let's change the list in shallow_copied_component and see if it changes in
|
||||
# component.
|
||||
shallow_copied_component.some_list_of_objects.append("another object")
|
||||
if component.some_list_of_objects[-1] == "another object":
|
||||
print(
|
||||
|
|
|
|||
Loading…
Reference in a new issue