StructuralC#verifiedVerified
Facade Pattern in C#
Provides a simplified, unified interface to a complex subsystem, hiding its internal complexity from clients.
How to Implement the Facade Pattern in C#
1Step 1: Complex subsystem classes
public class VideoDecoder
{
public string Decode(string filename) =>
$"Decoded video: {filename}";
}
public class AudioDecoder
{
public string Decode(string filename) =>
$"Decoded audio: {filename}";
}
public class Renderer
{
public string Render(string video, string audio) =>
$"Rendered: {video} + {audio}";
}2Step 2: Facade provides a simple interface
public class MediaPlayerFacade
{
private readonly VideoDecoder _video = new();
private readonly AudioDecoder _audio = new();
private readonly Renderer _renderer = new();
public string Play(string filename)
{
var video = _video.Decode(filename);
var audio = _audio.Decode(filename);
return _renderer.Render(video, audio);
}
}
// Usage:
// var player = new MediaPlayerFacade();
// Console.WriteLine(player.Play("movie.mp4"));using Microsoft.Extensions.Logging;
// [step] Complex subsystem: user registration services
public interface IUserRepository
{
Task<string> CreateAsync(string email, string passwordHash,
CancellationToken ct = default);
}
public interface IEmailService
{
Task SendWelcomeAsync(string email, string name,
CancellationToken ct = default);
}
public interface IPaymentService
{
Task<string> CreateCustomerAsync(string email,
CancellationToken ct = default);
}
public interface IAnalyticsService
{
Task TrackSignupAsync(string userId, string source,
CancellationToken ct = default);
}
// [step] DTOs for facade input/output
public record SignupRequest(
string Email, string Password, string Name,
string? ReferralSource = null);
public record SignupResult(
bool Success, string? UserId, string? CustomerId,
List<string> Errors);
// [step] Facade coordinates all services for a single operation
public sealed class UserRegistrationFacade(
IUserRepository userRepo,
IEmailService emailService,
IPaymentService paymentService,
IAnalyticsService analyticsService,
ILogger<UserRegistrationFacade> logger)
{
public async Task<SignupResult> SignupAsync(
SignupRequest request, CancellationToken ct = default)
{
var errors = new List<string>();
string? userId = null;
string? customerId = null;
try
{
// Step 1: Create user account
logger.LogInformation("Creating user: {Email}", request.Email);
var passwordHash = HashPassword(request.Password);
userId = await userRepo.CreateAsync(
request.Email, passwordHash, ct);
// Step 2: Create payment customer (non-blocking failure)
try
{
customerId = await paymentService.CreateCustomerAsync(
request.Email, ct);
}
catch (Exception ex)
{
logger.LogWarning(ex, "Payment setup deferred for {Email}",
request.Email);
errors.Add("Payment setup will be retried");
}
// Step 3: Send welcome email (fire and forget)
_ = emailService.SendWelcomeAsync(
request.Email, request.Name, CancellationToken.None);
// Step 4: Track analytics (fire and forget)
_ = analyticsService.TrackSignupAsync(
userId, request.ReferralSource ?? "direct",
CancellationToken.None);
logger.LogInformation("Signup complete: {UserId}", userId);
return new SignupResult(true, userId, customerId, errors);
}
catch (Exception ex)
{
logger.LogError(ex, "Signup failed for {Email}", request.Email);
errors.Add(ex.Message);
return new SignupResult(false, userId, customerId, errors);
}
}
private static string HashPassword(string password) =>
Convert.ToBase64String(
System.Security.Cryptography.SHA256.HashData(
System.Text.Encoding.UTF8.GetBytes(password)));
}Facade Pattern Architecture
hourglass_empty
Rendering diagram...
lightbulb
Facade Pattern in the Real World
“A hotel concierge is a facade for the city’s complex infrastructure. Instead of you directly calling a taxi company, booking a restaurant, and arranging a museum ticket separately, the concierge handles all of it through a single conversation. The underlying services still exist in their full complexity—you just don’t deal with them directly.”