π§© Facade Pattern
β Intentβ
- Provide a simple, unified interface to a complex subsystem
- Hide internal logic behind a clean and task-oriented entry point
β Motivationβ
- Simplify client responsibilities by exposing only whatβs necessary
- Help decouple client code from subsystem changes
β When to Useβ
- When a task involves multiple steps across services
- To provide a gateway for frameworks or module groups
- To simplify complex workflows for reuse and clarity
β Code Exampleβ
- TypeScript
- PHP
- Python
class AuthService {
authenticate(userId: string): boolean {
console.log(`γ¦γΌγΆγΌθͺθ¨Ό: ${userId}`);
return true;
}
}
class UserProfileService {
load(userId: string): object {
console.log(`γγγγ£γΌγ«εεΎ: ${userId}`);
return { name: "Hiroshi", id: userId };
}
}
class AuditService {
log(action: string) {
console.log(`[η£ζ»γγ°] ${action}`);
}
}
// Facade
class UserProfileFacade {
private auth = new AuthService();
private profile = new UserProfileService();
private audit = new AuditService();
show(userId: string) {
if (this.auth.authenticate(userId)) {
const profile = this.profile.load(userId);
console.log(profile);
this.audit.log("γγγγ£γΌγ«θ‘¨η€Ί");
}
}
}
// ε©η¨δΎ
const facade = new UserProfileFacade();
facade.show("user-123");
<?php
class AuthService {
public function authenticate(string $userId): bool {
echo "γ¦γΌγΆγΌθͺθ¨Ό: {$userId}\n";
return true;
}
}
class UserProfileService {
public function load(string $userId): array {
echo "γγγγ£γΌγ«εεΎ: {$userId}\n";
return ["name" => "Hiroshi", "id" => $userId];
}
}
class AuditService {
public function log(string $action): void {
echo "[η£ζ»γγ°] {$action}\n";
}
}
// Facade
class UserProfileFacade {
private AuthService $auth;
private UserProfileService $profile;
private AuditService $audit;
public function __construct() {
$this->auth = new AuthService();
$this->profile = new UserProfileService();
$this->audit = new AuditService();
}
public function show(string $userId): void {
if ($this->auth->authenticate($userId)) {
$profile = $this->profile->load($userId);
print_r($profile);
$this->audit->log("γγγγ£γΌγ«θ‘¨η€Ί");
}
}
}
// ε©η¨δΎ
$facade = new UserProfileFacade();
$facade->show("user-123");
class AuthService:
def authenticate(self, user_id: str) -> bool:
print(f"γ¦γΌγΆγΌθͺθ¨Ό: {user_id}")
return True
class UserProfileService:
def load(self, user_id: str) -> dict:
print(f"γγγγ£γΌγ«εεΎ: {user_id}")
return {"name": "Hiroshi", "id": user_id}
class AuditService:
def log(self, action: str):
print(f"[η£ζ»γγ°] {action}")
# Facade
class UserProfileFacade:
def __init__(self):
self.auth = AuthService()
self.profile = UserProfileService()
self.audit = AuditService()
def show(self, user_id: str):
if self.auth.authenticate(user_id):
profile = self.profile.load(user_id)
print(profile)
self.audit.log("γγγγ£γΌγ«θ‘¨η€Ί")
# ε©η¨δΎ
facade = UserProfileFacade()
facade.show("user-123")
β Explanationβ
This example applies the Facade
pattern to unify three distinct subsystems β AuthService
, UserProfileService
, and AuditService
β under a simple interface.
The UserProfileFacade
class consolidates these into a single show(userId)
call that handles authentication, profile retrieval, and audit logging.
1. Facade Pattern Overviewβ
-
Subsystem Classes: Provide individual pieces of logic
- In this example:
AuthService
,UserProfileService
,AuditService
- In this example:
-
Facade: Simplifies access to the subsystems through a unified interface
- Here:
UserProfileFacade
- Here:
-
Client: Uses the facade to complete a complex task via a single call
- Here:
facade.show("user-123")
- Here:
2. Key Classes and Rolesβ
-
AuthService
- Authenticates the user
-
UserProfileService
- Fetches user profile information
-
AuditService
- Logs the profile access action
-
UserProfileFacade
- Encapsulates the entire workflow into a single
show()
method
- Encapsulates the entire workflow into a single
-
Client Code
- Calls only
UserProfileFacade.show()
instead of dealing with each subsystem separately
- Calls only
3. UML Class Diagramβ
4. Benefits of the Facade Patternβ
- Simplified Interface: Reduces the learning curve and usage complexity
- Decoupling: Hides internal subsystem logic from the client
- Improved Maintainability: Internal changes are absorbed by the facade, not the client
This design is especially helpful when internal complexity needs to be hidden to promote reuse and cleaner interfaces.
It enhances both usability and maintainability by preventing business logic from leaking into calling code.