Definition
‘Factory Method’ pattern là một creational design pattern , trừu tượng hóa quá trình khởi tạo. Mô hình sáng tạo kiểm soát ai tạo ra một đối tượng và cái gì / như thế nào / khi nào nó được tạo.
The ‘Factory Method’ pattern xác định interface để tạo đối tượng và ủy quyền việc tạo đối tượng cho các lớp con.
When should we use this pattern?
Cung cấp interface để tạo đối tượng
Pattern này nên được sử dụng khi chúng ta có nhiều đối tượng khác nhau mà chúng ta sử dụng theo những cách khác nhau. Khởi tạo của họ có thể phức tạp và cần tính toán để tạo ra chúng. The ‘Factory Method’ pattern đóng gói các phần khởi tạo của chúng để đơn giản hóa các sáng tạo của chúng trên các địa điểm.
Xác định một nơi duy nhất để khởi tạo
Pattern này nên được sử dụng khi một lớp không thể lường trước được loại đối tượng mà nó cần tạo. Nếu chúng ta có một đối tượng đã làm những gì chúng ta cần, chúng ta phải sử dụng lại và khởi tạo nó ở đâu đó trong mã. Di chuyển các tức thời này, từ lớp máy khách sang một giao diện, làm cho lớp phụ thuộc vào sự trừu tượng hóa và không làm cho nó phụ thuộc vào các thành phần cấp thấp (Nguyên tắc đảo ngược phụ thuộc). Interface này, được gọi là phương thức nhà máy, có logic để xác định loại đối tượng chúng ta cần khởi tạo. Hơn nữa, việc ủy thác logic tạo cho một lớp con sẽ tránh việc sao chép mã và cung cấp một nơi duy nhất để bảo trì.
Để tách riêng việc thực hiện một đối tượng khỏi việc sử dụng nó
Pattern này nên được sử dụng khi logic tạo và khởi tạo được thực hiện bởi máy khách. Một máy khách được liên kết chặt chẽ với một đối tượng nếu loại của nó được sử dụng trong lớp của nó. Bằng cách di chuyển logic và khởi tạo các đối tượng trong một lớp con, chúng tôi bảo vệ mã khỏi các thay đổi API. Nếu một số sửa đổi được thêm vào một lớp cụ thể và API của nó, mã máy khách sẽ không bị ảnh hưởng bởi những thay đổi mà nó không quan tâm. Bằng cách triển khai một giao diện, phương thức xuất xưởng trả về một sự trừu tượng hơn là một kiểu cụ thể để chúng tôi bảo vệ mã khỏi các chi tiết triển khai.
How should we use this pattern?
Hãy bắt đầu với một cách tiếp cận phổ biến của mô hình này. Trong ví dụ này, chúng ta đang làm việc trên một ứng dụng di động và chúng tôi muốn tạo một phương thức factory method chịu trách nhiệm tạo các thành phần UI.
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 | <span class="token keyword">class</span> <span class="token class-name">ComponentFactory</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> <span class="token keyword">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">static</span> <span class="token keyword">func</span> <span class="token function">createView</span><span class="token punctuation">(</span>component<span class="token punctuation">:</span> <span class="token builtin">ComponentType</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">UIView</span> <span class="token punctuation">{</span> <span class="token keyword">switch</span> component <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token punctuation">.</span>textfield<span class="token punctuation">:</span> <span class="token keyword">let</span> textfield <span class="token operator">=</span> <span class="token function">UITextField</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// textfield customatization...</span> <span class="token keyword">return</span> textfield <span class="token keyword">case</span> <span class="token punctuation">.</span><span class="token keyword">switch</span><span class="token punctuation">:</span> <span class="token keyword">let</span> `<span class="token keyword">switch</span>` <span class="token operator">=</span> <span class="token function">UISwitch</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// `switch` customatization...</span> <span class="token keyword">return</span> `<span class="token keyword">switch</span>` <span class="token keyword">case</span> <span class="token punctuation">.</span>button<span class="token punctuation">:</span> <span class="token keyword">let</span> button <span class="token operator">=</span> <span class="token function">UIButton</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// button customatization...</span> <span class="token keyword">return</span> button <span class="token keyword">case</span> <span class="token punctuation">.</span>label<span class="token punctuation">:</span> <span class="token keyword">let</span> label <span class="token operator">=</span> <span class="token function">UILabel</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// label customatization...</span> <span class="token keyword">return</span> label <span class="token keyword">case</span> <span class="token punctuation">.</span>image<span class="token punctuation">:</span> <span class="token keyword">let</span> image <span class="token operator">=</span> <span class="token function">UIImageView</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// image customatization...</span> <span class="token keyword">return</span> image <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Implementation
Factory Method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token keyword">protocol</span> <span class="token builtin">ComponentFactory</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">createView</span><span class="token punctuation">(</span>component<span class="token punctuation">:</span> <span class="token builtin">ComponentType</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">UIView</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">DisneyComponentFactory</span><span class="token punctuation">:</span> <span class="token builtin">ComponentFactory</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">createView</span><span class="token punctuation">(</span>component<span class="token punctuation">:</span> <span class="token builtin">ComponentType</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">UIView</span> <span class="token punctuation">{</span> <span class="token keyword">switch</span> component <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token punctuation">.</span>textfield<span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token function">DisneyTextField</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token punctuation">.</span><span class="token keyword">switch</span><span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token function">DisneySwitch</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token punctuation">.</span>button<span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token function">DisneyButton</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token punctuation">.</span>label<span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token function">DisneyLabel</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token punctuation">.</span>image<span class="token punctuation">:</span> <span class="token keyword">return</span> <span class="token function">DisneyImageView</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Run code in a Playground
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 | <span class="token comment">// ‼️ This online playground is platform agnostic, so we need to declare a UIView interface and its subclasses.</span> <span class="token keyword">protocol</span> <span class="token builtin">UIView</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">UITextField</span><span class="token punctuation">:</span> <span class="token builtin">UIView</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">UISwitch</span><span class="token punctuation">:</span> <span class="token builtin">UIView</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">UIButton</span><span class="token punctuation">:</span> <span class="token builtin">UIView</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">UILabel</span><span class="token punctuation">:</span> <span class="token builtin">UIView</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">UIImageView</span><span class="token punctuation">:</span> <span class="token builtin">UIView</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">DisneyTextField</span><span class="token punctuation">:</span> <span class="token builtin">UITextField</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">DisneySwitch</span><span class="token punctuation">:</span> <span class="token builtin">UISwitch</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">DisneyButton</span><span class="token punctuation">:</span> <span class="token builtin">UIButton</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">DisneyLabel</span><span class="token punctuation">:</span> <span class="token builtin">UILabel</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">DisneyImageView</span><span class="token punctuation">:</span> <span class="token builtin">UIImageView</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">enum</span> <span class="token builtin">ComponentType</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> textfield <span class="token keyword">case</span> `<span class="token keyword">switch</span>` <span class="token keyword">case</span> button <span class="token keyword">case</span> label <span class="token keyword">case</span> image <span class="token punctuation">}</span> <span class="token keyword">protocol</span> <span class="token builtin">ComponentFactory</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">createView</span><span class="token punctuation">(</span>component<span class="token punctuation">:</span> <span class="token builtin">ComponentType</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">UIView</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">DisneyComponentFactory</span><span class="token punctuation">:</span> <span class="token builtin">ComponentFactory</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">createView</span><span class="token punctuation">(</span>component<span class="token punctuation">:</span> <span class="token builtin">ComponentType</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">UIView</span> <span class="token punctuation">{</span> <span class="token keyword">switch</span> component <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token punctuation">.</span>textfield<span class="token punctuation">:</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"DisneyTextField created"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">DisneyTextField</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token punctuation">.</span><span class="token keyword">switch</span><span class="token punctuation">:</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"DisneySwitch created"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">DisneySwitch</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token punctuation">.</span>button<span class="token punctuation">:</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"DisneyButton created"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">DisneyButton</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token punctuation">.</span>label<span class="token punctuation">:</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"DisneyLabel created"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">DisneyLabel</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">case</span> <span class="token punctuation">.</span>image<span class="token punctuation">:</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"DisneyImageView created"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">DisneyImageView</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// Client</span> <span class="token keyword">let</span> disneyFactory <span class="token operator">=</span> <span class="token function">DisneyComponentFactory</span><span class="token punctuation">(</span><span class="token punctuation">)</span> disneyFactory<span class="token punctuation">.</span><span class="token function">createView</span><span class="token punctuation">(</span>component<span class="token punctuation">:</span> <span class="token punctuation">.</span>label<span class="token punctuation">)</span> |