Skip to content

Instantly share code, notes, and snippets.

@eladcandroid
Created September 18, 2025 14:43
Show Gist options
  • Save eladcandroid/bceed714c7b3a22f902e629913e37da6 to your computer and use it in GitHub Desktop.
Save eladcandroid/bceed714c7b3a22f902e629913e37da6 to your computer and use it in GitHub Desktop.
Angular Facade Pattern Example - Simplifies complex subsystem interactions by providing a unified interface
// Complex subsystems
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of, throwError, BehaviorSubject } from 'rxjs';
import { tap } from 'rxjs/operators';
// User Model
export interface User {
id: string;
name: string;
email: string;
age: number;
}
// API Service
@Injectable()
export class UserApiService {
constructor(private http: HttpClient) {}
getUser(id: string): Observable<User> {
return this.http.get<User>(`/api/users/${id}`);
}
updateUser(id: string, data: Partial<User>): Observable<User> {
return this.http.patch<User>(`/api/users/${id}`, data);
}
}
// Cache Service
@Injectable()
export class UserCacheService {
private cache = new Map<string, User>();
set(id: string, user: User): void {
this.cache.set(id, user);
}
get(id: string): User | undefined {
return this.cache.get(id);
}
clear(): void {
this.cache.clear();
}
}
// Validation Service
@Injectable()
export class UserValidationService {
validateEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
validateAge(age: number): boolean {
return age >= 18 && age <= 120;
}
}
// FACADE SERVICE - Simplifies complex subsystem interactions
@Injectable({
providedIn: 'root'
})
export class UserFacadeService {
private currentUser$ = new BehaviorSubject<User | null>(null);
constructor(
private userApi: UserApiService,
private userCache: UserCacheService,
private userValidation: UserValidationService
) {}
// Simplified interface for components
getCurrentUser(): Observable<User | null> {
return this.currentUser$.asObservable();
}
loadUser(id: string): Observable<User> {
// Check cache first
const cachedUser = this.userCache.get(id);
if (cachedUser) {
this.currentUser$.next(cachedUser);
return of(cachedUser);
}
// Load from API and cache
return this.userApi.getUser(id).pipe(
tap(user => {
this.userCache.set(id, user);
this.currentUser$.next(user);
})
);
}
updateUserProfile(id: string, email: string, age: number): Observable<User> {
// Validate
if (!this.userValidation.validateEmail(email)) {
return throwError(() => new Error('Invalid email format'));
}
if (!this.userValidation.validateAge(age)) {
return throwError(() => new Error('Invalid age'));
}
// Update
return this.userApi.updateUser(id, { email, age }).pipe(
tap(user => {
this.userCache.set(id, user);
this.currentUser$.next(user);
})
);
}
logout(): void {
this.currentUser$.next(null);
this.userCache.clear();
}
}// Component usage - clean and simple
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { UserFacadeService, User } from './user-facade.service';
@Component({
selector: 'app-user-profile',
template: `
<div *ngIf="user$ | async as user" class="user-profile">
<h2>{{ user.name }}</h2>
<p>Email: {{ user.email }}</p>
<p>Age: {{ user.age }}</p>
<div class="actions">
<button (click)="updateProfile()">Update Profile</button>
<button (click)="logout()">Logout</button>
</div>
</div>
`,
styles: [`
.user-profile {
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
}
.actions {
margin-top: 20px;
}
button {
margin-right: 10px;
padding: 10px 20px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
`]
})
export class UserProfileComponent {
user$: Observable<User | null> = this.userFacade.getCurrentUser();
constructor(private userFacade: UserFacadeService) {}
ngOnInit(): void {
// Load user on component init
this.userFacade.loadUser('123').subscribe();
}
updateProfile(): void {
// Simple method call - complexity is hidden in facade
this.userFacade.updateUserProfile('123', '[email protected]', 25)
.subscribe(
user => console.log('Profile updated:', user),
error => console.error('Update failed:', error)
);
}
logout(): void {
this.userFacade.logout();
console.log('User logged out');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment