> For the complete documentation index, see [llms.txt](https://zeliang-yao.gitbook.io/my-note-zeliang-yao/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://zeliang-yao.gitbook.io/my-note-zeliang-yao/useful/design-patterns/creational-patterns.md).

# Creational Patterns

## Factory pattern

### Simple Factory

> Without factory

```python

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

> With simple factory

```python
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

```python
#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

```python
#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)

{% embed url="<https://segmentfault.com/a/1190000013053013>" %}

## Personal example

Read data from csv and filter on it based on requirements

```python
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()
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://zeliang-yao.gitbook.io/my-note-zeliang-yao/useful/design-patterns/creational-patterns.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
