Modèles structurels en Python

Decorator Decorators are great tools to add additional features to an existing object without using subclassing.

from functools import wraps

def make_blink(function):
	"""Defines the decorator"""

	#This makes the decorator transparent in terms of its name and docstring
	@wraps(function)

	#Define the inner function
	def decorator():
		#Grab the return value of the function being decorated
		ret = function() 

		#Add new functionality to the function being decorated
		return "<blink>" + ret + "</blink>"

	return decorator

#Apply the decorator here!
@make_blink
def hello_world():
	"""Original function! """

	return "Hello, World!"

#Check the result of decorating
print(hello_world())

#Check if the function name is still the same name of the function being decorated
print(hello_world.__name__)

#Check if the docstring is still the same as that of the function being decorated
print(hello_world.__doc__)

Proxy Proxy comes in handy when creating an object that is very resource-intensive. It can postpone object creation unless it's absolutely necessary by creating a placeholder.

import time

class Producer:
	"""Define the 'resource-intensive' object to instantiate!"""
	def produce(self):
		print("Producer is working hard!")

	def meet(self):
		print("Producer has time to meet you now!")

class Proxy:
	""""Define the 'relatively less resource-intensive' proxy to instantiate as a middleman"""
	def __init__(self):  
		self.occupied = 'No'
		self.producer = None

	def produce(self):
		"""Check if Producer is available"""
		print("Artist checking if Producer is available ...")

		if self.occupied == 'No':
			#If the producer is available, create a producer object!
			self.producer = Producer()
			time.sleep(2)

			#Make the prodcuer meet the guest!
			self.producer.meet()
			
		else:
			#Otherwise, don't instantiate a producer 
			time.sleep(2)
			print("Producer is busy!")

#Instantiate a Proxy
p = Proxy()

#Make the proxy: Artist produce until Producer is available
p.produce()

#Change the state to 'occupied'
p.occupied = 'Yes'

#Make the Producer produce
p.produce()

Adapter This is used when the interfaces are incompatible between a client and a server.

class Korean:
	"""Korean speaker"""
	def __init__(self):
		self.name = "Korean"

	def speak_korean(self):
		return "An-neyong?"

class British:
	"""English speaker"""
	def __init__(self):
		self.name = "British"	

	#Note the different method name here!
	def speak_english(self):
		return "Hello!"	

class Adapter:
	"""This changes the generic method name to individualized method names"""

	def __init__(self, object, **adapted_method):
		"""Change the name of the method"""
		self._object = object

		#Add a new dictionary item that establishes the mapping between the generic method name: speak() and the concrete method
		#For example, speak() will be translated to speak_korean() if the mapping says so
		self.__dict__.update(adapted_method)

	def __getattr__(self, attr):
		"""Simply return the rest of attributes!"""
		return getattr(self._object, attr)
		
#List to store speaker objects
objects = []

#Create a Korean object
korean = Korean()

#Create a British object
british =British()

#Append the objects to the objects list
objects.append(Adapter(korean, speak=korean.speak_korean))
objects.append(Adapter(british, speak=british.speak_english))


for obj in objects:
	print("{} says '{}'\n".format(obj.name, obj.speak()))

Composite The composite design pattern maintains a tree data structure to represent part-whole relationships. Here we like to build a recursive tree data structure so that an element of the tree can have its own sub-elements.

class Component(object):
	"""Abstract class"""

	def __init__(self, *args, **kwargs):
		pass

	def component_function(self):
		pass

class Child(Component): #Inherits from the abstract class, Component
	"""Concrete class"""

	def __init__(self, *args, **kwargs):
		Component.__init__(self, *args, **kwargs)

		#This is where we store the name of your child item!
		self.name = args[0]

	def component_function(self):
		#Print the name of your child item here!
		print("{}".format(self.name))

class Composite(Component): #Inherits from the abstract class, Component
	"""Concrete class and maintains the tree recursive structure"""

	def __init__(self, *args, **kwargs):
		Component.__init__(self, *args, **kwargs)

		#This is where we store the name of the composite object
		self.name = args[0]

		#This is where we keep our child items
		self.children = []

	def append_child(self, child):
		"""Method to add a new child item"""
		self.children.append(child)

	def remove_child(self, child):
		"""Method to remove a child item"""
		self.children.remove(child)

	def component_function(self):

		#Print the name of the composite object
		print("{}".format(self.name))

		#Iterate through the child objects and invoke their component function printing their names
		for i in self.children:
			i.component_function()

#Build a composite submenu 1
sub1 = Composite("submenu1")

#Create a new child sub_submenu 11
sub11 = Child("sub_submenu 11")
#Create a new Child sub_submenu 12
sub12 = Child("sub_submenu 12")

#Add the sub_submenu 11 to submenu 1
sub1.append_child(sub11)
#Add the sub_submenu 12 to submenu 1
sub1.append_child(sub12)

#Build a top-level composite menu
top = Composite("top_menu")

#Build a submenu 2 that is not a composite
sub2 = Child("submenu2")

#Add the composite submenu 1 to the top-level composite menu
top.append_child(sub1)

#Add the plain submenu 2 to the top-level composite menu
top.append_child(sub2)

#Let's test if our Composite pattern works!
top.component_function()

Bridge The bridge pattern helps untangle an unnecessary complicated class hierarchy, especially when implementation specific classes are mixed together with implementation-indendent classes. So our problem here is that there are two parallel or orthogonal abstractions. One is implementation-specific, and the other one is implementation-independent.

class DrawingAPIOne(object):
	"""Implementation-specific abstraction: concrete class one"""
	def draw_circle(self, x, y, radius):
		print("API 1 drawing a circle at ({}, {} with radius {}!)".format(x, y, radius))


class DrawingAPITwo(object):
	"""Implementation-specific abstraction: concrete class two"""
	def draw_circle(self, x, y, radius):
		print("API 2 drawing a circle at ({}, {} with radius {}!)".format(x, y, radius))

class Circle(object):
	"""Implementation-independent abstraction: for example, there could be a rectangle class!"""

	def __init__(self, x, y, radius, drawing_api):
		"""Initialize the necessary attributes"""
		self._x = x
		self._y = y
		self._radius = radius
		self._drawing_api = drawing_api

	def draw(self):
		"""Implementation-specific abstraction taken care of by another class: DrawingAPI"""
		self._drawing_api.draw_circle(self._x, self._y, self._radius)

	def scale(self, percent):
		"""Implementation-independent"""
		self._radius *= percent


#Build the first Circle object using API One
circle1 = Circle(1, 2, 3, DrawingAPIOne())
#Draw a circle
circle1.draw()

#Build the second Circle object using API Two
circle2 = Circle(2, 3, 4, DrawingAPITwo())
#Draw a circle
circle2.draw()

More Design Patterns in Python

Recommended Posts

Modèles structurels en Python
Modèles comportementaux en Python
Modèles de création en Python
Modèles de conception en Python: introduction
Quadtree en Python --2
CURL en Python
Métaprogrammation avec Python
Python 3.3 avec Anaconda
Géocodage en python
SendKeys en Python
Méta-analyse en Python
Unittest en Python
Discord en Python
DCI en Python
tri rapide en python
nCr en python
N-Gram en Python
Programmation avec Python
Plink en Python
Constante en Python
FizzBuzz en Python
Sqlite en Python
Étape AIC en Python
LINE-Bot [0] en Python
CSV en Python
Assemblage inversé avec Python
Réflexion en Python
Constante en Python
nCr en Python.
format en python
Scons en Python 3
Puyopuyo en python
python dans virtualenv
PPAP en Python
Quad-tree en Python
Réflexion en Python
Chimie avec Python
Hashable en Python
DirectLiNGAM en Python
LiNGAM en Python
Aplatir en Python
Aplatir en python
Modèles Gang of Four (GoF) en Python
Liste triée en Python
AtCoder # 36 quotidien avec Python
Texte de cluster en Python
AtCoder # 2 tous les jours avec Python
Daily AtCoder # 32 en Python
Daily AtCoder # 6 en Python
Modifier les polices en Python
Motif singleton en Python
Opérations sur les fichiers en Python
Lire DXF avec python
Daily AtCoder # 53 en Python
Séquence de touches en Python
Utilisez config.ini avec Python
Daily AtCoder # 33 en Python
Résoudre ABC168D en Python