Intent (general)
Facade is a structural design pattern
provides a simple interface for libraries, frameworks, or any other complex set of classes.
Problem
Imagine that you have to make your code work with a set of objects that belong to a library or framework. Normally, you need to initialize all those objects, track dependencies, execute methods in the correct order, etc.
Therefore, the business logic in your classes will become closely associated with the implementation details of 3rd party classes, making it difficult to understand and maintain.
Solution
The facade is a class that provides a simple interface for a complex subsystem that contains many moving parts. A facade can provide limited functionality compared to working directly with the subsystem. However, it only includes features that the customer really cares about.
The facade is handy when you need to integrate your application with a sophisticated library that has dozens of features, but you only need a bit of functionality.
For example, you have an application that helps upload funny short videos with cats to social media, using a professional video conversion library. However, all you really need is a single encode(filename, format)
. After creating a class with such a method and connecting it to the video conversion library, you will have the first facade .
Real-World Analogy (contact with reality)
When you call a store to order by phone, an operator is your facade for all departmental services in the store. The operator provides you with a simple voice interface for ordering systems, payment gateways and various delivery services.
Structure (organization)
- Facade provides convenient access to a specific part of the subsystem function. It knows where to perform client requests and how all components operate.
- Additional Facade can be created to prevent pollution of a facade , extraneous features can make it another complex structure. Additional Facade can be used by both the Client and other facade .
- Complex Subsystem includes dozens of different objects. To make all of them do something meaningful, you have to go into the subsystem implementation details, like initializing objects in the correct order and providing them data in the appropriate format. The subsystem class doesn't know about the existence of Facade . They operate in the system and work directly with each other.
- Clients use Facade instead of calling subsystem objects directly.
Applicability (use when)
- Use the Facade template when you need a limited but simple interface with complex subsystems.
- Use Facade when you want to structure a subsystem into layers.
How to Implement (how to install)
- Check to see if you can provide a simpler interface than what the existing subsystem has to offer. You can go in the right direction if this interface makes the client code independent of the sub-class of the subsystem.
- Declare and implement this interface on the new facade class. Facade will redirect calls from the client code to the appropriate objects of the subsystem. Facade is responsible for initializing the subsystem and managing its next life cycle unless the client code has done this.
- To get the full benefit of the pattern, make all client code communicate only with the subsystem via the facade. The client code is now separate from any changes in subsystem code. For example, when a subsystem is upgraded to the new version, you'll only need to modify the code on the facade.
- If the facade becomes too large, consider extracting part of its behavior into a new facade class, be subtle.
Decorator in Ruby (example with ruby language)
main.rb:
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | <span class="token comment"># Lớp Facade cung cấp một giao diện đơn giản cho logic phức tạp </span> <span class="token comment"># của một hoặc một số hệ thống con.</span> <span class="token comment"># Facade ủy thác các yêu cầu của client cho các đối tượng</span> <span class="token comment"># thích hợp trong hệ thống con.</span> <span class="token comment"># Facade cũng chịu trách nhiệm quản lý vòng đời của họ.</span> <span class="token comment"># Tất cả điều này bảo vệ client khỏi sự phức tạp </span> <span class="token comment"># không mong muốn của hệ thống con.</span> <span class="token keyword">class</span> <span class="token class-name">Facade</span> <span class="token comment"># Tùy thuộc vào nhu cầu của ứng dụng của bạn,</span> <span class="token comment"># bạn có thể cung cấp cho Facade các đối tượng hệ thống con hiện có</span> <span class="token comment"># hoặc buộc Facade phải tự tạo chúng.</span> <span class="token keyword">def</span> <span class="token function">initialize</span> <span class="token punctuation">(</span> subsystem1 <span class="token punctuation">,</span> subsystem2 <span class="token punctuation">)</span> <span class="token variable">@subsystem1</span> <span class="token operator">=</span> subsystem1 <span class="token operator">||</span> <span class="token constant">Subsystem1</span> <span class="token punctuation">.</span> <span class="token keyword">new</span> <span class="token variable">@subsystem2</span> <span class="token operator">=</span> subsystem2 <span class="token operator">||</span> <span class="token constant">Subsystem2</span> <span class="token punctuation">.</span> <span class="token keyword">new</span> <span class="token class-name">end</span> <span class="token comment"># Các phương thức của Facade là các shortcut thuận tiện cho chức năng tinh vi</span> <span class="token comment"># của các hệ thống con.</span> <span class="token comment"># Tuy nhiên, client chỉ nhận được một phần khả năng của hệ thống con.</span> <span class="token keyword">def</span> operation results <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> results <span class="token punctuation">.</span> <span class="token function">append</span> <span class="token punctuation">(</span> <span class="token string">'Facade initializes subsystems:'</span> <span class="token punctuation">)</span> results <span class="token punctuation">.</span> <span class="token function">append</span> <span class="token punctuation">(</span> <span class="token variable">@subsystem1</span> <span class="token punctuation">.</span> operation1 <span class="token punctuation">)</span> results <span class="token punctuation">.</span> <span class="token function">append</span> <span class="token punctuation">(</span> <span class="token variable">@subsystem2</span> <span class="token punctuation">.</span> operation1 <span class="token punctuation">)</span> results <span class="token punctuation">.</span> <span class="token function">append</span> <span class="token punctuation">(</span> <span class="token string">'Facade orders subsystems to perform the action:'</span> <span class="token punctuation">)</span> results <span class="token punctuation">.</span> <span class="token function">append</span> <span class="token punctuation">(</span> <span class="token variable">@subsystem1</span> <span class="token punctuation">.</span> operation_n <span class="token punctuation">)</span> results <span class="token punctuation">.</span> <span class="token function">append</span> <span class="token punctuation">(</span> <span class="token variable">@subsystem2</span> <span class="token punctuation">.</span> operation_z <span class="token punctuation">)</span> results <span class="token punctuation">.</span> <span class="token function">join</span> <span class="token punctuation">(</span> <span class="token string">"n"</span> <span class="token punctuation">)</span> <span class="token keyword">end</span> <span class="token keyword">end</span> <span class="token comment"># Hệ thống con có thể chấp nhận các yêu cầu từ facade hoặc client trực tiếp.</span> <span class="token comment"># Trong mọi trường hợp, đối với Hệ thống con, Facade vẫn là một ứng dụng client khác </span> <span class="token comment"># và nó không phải là một phần của Hệ thống con.</span> <span class="token keyword">class</span> <span class="token class-name">Subsystem1</span> <span class="token comment"># @return [String]</span> <span class="token keyword">def</span> operation1 <span class="token string">'Subsystem1: Ready!'</span> <span class="token keyword">end</span> <span class="token comment"># ...</span> <span class="token comment"># @return [String]</span> <span class="token keyword">def</span> operation_n <span class="token string">'Subsystem1: Go!'</span> <span class="token keyword">end</span> <span class="token keyword">end</span> <span class="token comment"># Một số facade có thể làm việc với nhiều hệ thống con cùng một lúc.</span> <span class="token keyword">class</span> <span class="token class-name">Subsystem2</span> <span class="token comment"># @return [String]</span> <span class="token keyword">def</span> operation1 <span class="token string">'Subsystem2: Get ready!'</span> <span class="token keyword">end</span> <span class="token comment"># ...</span> <span class="token comment"># @return [String]</span> <span class="token keyword">def</span> operation_z <span class="token string">'Subsystem2: Fire!'</span> <span class="token keyword">end</span> <span class="token keyword">end</span> <span class="token comment"># Client code hoạt động với các hệ thống con phức tạp thông qua giao diện đơn giản</span> <span class="token comment"># do Facade cung cấp.</span> <span class="token comment"># Khi một facade quản lý vòng đời của hệ thống con, client thậm chí</span> <span class="token comment"># có thể không biết về sự tồn tại của hệ thống con.</span> <span class="token comment"># Cách tiếp cận này cho phép bạn giữ sự phức tạp trong tầm kiểm soát.</span> <span class="token keyword">def</span> <span class="token function">client_code</span> <span class="token punctuation">(</span> facade <span class="token punctuation">)</span> print facade <span class="token punctuation">.</span> operation <span class="token keyword">end</span> <span class="token comment"># Mã máy khách có thể có một số đối tượng của hệ thống con đã được tạo.</span> <span class="token comment"># Trong trường hợp này, có thể đáng để khởi tạo Facade</span> <span class="token comment"># với các đối tượng này thay vì để Facade tạo phiên bản mới.</span> subsystem1 <span class="token operator">=</span> <span class="token constant">Subsystem1</span> <span class="token punctuation">.</span> <span class="token keyword">new</span> <span class="token class-name">subsystem2</span> <span class="token operator">=</span> <span class="token constant">Subsystem2</span> <span class="token punctuation">.</span> <span class="token keyword">new</span> <span class="token class-name">facade</span> <span class="token operator">=</span> <span class="token constant">Facade</span> <span class="token punctuation">.</span> <span class="token keyword">new</span> <span class="token punctuation">(</span> subsystem1 <span class="token punctuation">,</span> subsystem2 <span class="token punctuation">)</span> <span class="token function">client_code</span> <span class="token punctuation">(</span> facade <span class="token punctuation">)</span> |
output.txt:
1 2 3 4 5 6 7 | Facade initializes subsystems: Subsystem1: Ready! Subsystem2: Get ready! Facade orders subsystems to perform the action: Subsystem1: Go! Subsystem2: Fire! |