Creational Patterns

Factory pattern

Simple Factory

Without factory


    class Mercedes(object):
        def __repr__(self):
            return "Mercedes-Benz"
    
    class BMW(object):
        def __repr__(self):
            return "BMW"
            
mercedes = Mercedes()
bmw = BMW()

With simple factory

class SimpleCarFactory(object):
    @staticmethod
    def product_car(name):
        if name == 'mb':
            return Mercedes()
        elif name == 'bmw':
            return BMW()
            
c1 = SimpleCarFactory.product_car('mb')
c2 = SimpleCarFactory.product_car('bmw')

Factory Method

Use abstract factory methode to add flexibility

#coding=utf-8
import abc

class AbstractFactory(object):

    __metaclass__ = abc.ABCMeta

 @abc.abstractmethod
    def product_car(self):
        pass

class MercedesFactory(AbstractFactory):

    def product_car(self):
        return Mercedes()

class BMWFactory(AbstractFactory):
    def product_car(self):
        return BMW()
        
c1 = MercedesFactory().product_car()
c2 = BMWFactory().product_car()

Abstract factory

Now let's make it better, we can produce SUV or normal car

#coding=utf-8
import abc

# 两种小汽车
class Mercedes_C63(object):
    def __repr__(self):
        return "Mercedes-Benz: C63"

class BMW_M3(object):
 
    def __repr__(self):
        return "BMW: M3"

class Mercedes_G63(object):
    def __repr__(self):
        return "Mercedes-Benz: G63"

class BMW_X5(object):
 
    def __repr__(self):
        return "BMW: X5"

class AbstractFactory(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def product_car(self):
        pass

    @abc.abstractmethod
    def product_suv(self):
        pass

class MercedesFactory(AbstractFactory):
  
    def product_car(self):
        return Mercedes_C63()

    def product_suv(self):
        return Mercedes_G63()

class BMWFactory(AbstractFactory):

    def product_car(self):
        return BMW_M3()

    def product_suv(self):
        return BMW_X5()
        
c1 = MercedesFactory().product_car()
s1 = MercedesFactory().product_suv()
print(c1, s1)
s2 = BMWFactory().product_suv()
c2 = BMWFactory().product_car()
print(c2, s2)

Reference (Chinese)

Personal example

Read data from csv and filter on it based on requirements

import hashlib
import abc
from collections import namedtuple

# Build data type
basic_cols = ['a','b','c'... ,'hash_d=id']
fields = " ".join(basic_cols)
Data = namedtuple('Data',fields,defaults=""* len(fields))



class Datafactory:
	__metaclass__ = abc.ABCMeta
	source = []
	def __init__(self,file_name):
	    if self.source==[]:
		print("Reading data...")
		with open(file_name,encoding='utf-8') as file:
	            file_iter = iter(file)
		    # Jump first line
		    _ = next(file_iter)
		    for line in file_iter:
	                each_ine = line.strip("\n").split(";")+['']
			self.source.append(Data(*each_line))
			print("Finish")
			print("Add hash_id ...")
			self.source = list(map(self.create_hash_id,self.source))
	@staticmethod
	def create_hash_id(each):
		text = "".join(x.replace(" ","") for x in each._asdict().values())
		return each._replace(hash_id = hashlib.sha256(text.encode('utf-8').hexdigest())	
	
	@abc.abstractmethod
	def produce_data(self):
		pass


class D1_Factory(DataFactory):
	def __init__(self,file_name):
		super().__init__(file_name)
		print("Apply D1 filter...")
		self.d1_data = list(filter(self.apply_filter,self.source))	
		print("Done")

	@staticmethod
	def apply_filter(e):
		return (e.a=='xxx' and e.b in [1,24] and ..)
	
	def produce_data(self):
		return pd.DataFrame(self.d1_data,columns = Data._fields)
	
class C1_Factory(DataFactory):
	def __init__(self,file_name):
		super().__init__(file_name)
		print("Apply C1 filter...")
		self.c1_data= list(filter(self.apply_filter,self.source))	
		print("Done")

	@staticmethod
	def apply_filter(e):
		return (e.c=='c1')
	
	def produce_data(self):
		return pd.DataFrame(self.c1_data,columns = Data._fields)


D1_data = D1_Factory('data.csv').produce_data()
C1_data = C1_Factory('data.csv').produce_data()

Last updated