Facade: مبانی الگوی فاساد در معماری موبایل

نویسنده: IT Sectr منتشر شده: 2026-02-18 زمان مطالعه: 9 دقیقه

Facade — یک الگوی طراحی ساختاری است که یک رابط ساده‌شده به زیرسیستم پیچیده‌ای از کلاس‌ها ارائه می‌دهد. در توسعه موبایل، Facade اغلب به‌صورت Service Layer یا UseCase پیاده‌سازی می‌شود که تعامل با شبکه، پایگاه داده و تحلیل را پنهان می‌کند. بر اساس Martin Fowler (Patterns of Enterprise Application Architecture, 2003)، Facade یکی از الگوهای کلیدی برای سازمان‌دهی لایه سرویس است.

نکات اصلی

  • Facade — الگوی ساختاری که رابطی ساده به سیستم پیچیده‌ای از کلاس‌ها، کتابخانه‌ها یا فریمورک‌ها ارائه می‌دهد
  • Service Layer — پیاده‌سازی Facade در معماری موبایل که API، کش و تحلیل را از UI پنهان می‌کند
  • Facade زیرسیستم را پنهان نمی‌کند — کلاینت در صورت نیاز می‌تواند مستقیماً به آن دسترسی داشته باشد
  • UseCase در Clean Architecture — گونه‌ای از Facade که یک سناریوی تجاری را ارکستر می‌کند
  • Facade در برابر Adapter: Facade رابط را ساده می‌کند، Adapter یک رابط را به رابط دیگر تبدیل می‌کند

الگوی Facade چیست؟

Facade — الگوی ساختاری که یک رابط یکپارچه به گروهی از رابط‌های زیرسیستم ارائه می‌دهد. این الگو یک رابط سطح بالا تعریف می‌کند که استفاده از زیرسیستم را ساده می‌کند. Facade قابلیت جدیدی اضافه نمی‌کند — مؤلفه‌های موجود را ارکستر می‌کند و پیچیدگی تعامل آن‌ها را از کلاینت پنهان می‌کند.

Kotlin
// زیرسیستم پیچیده
class AuthApi {
    suspend fun login(email: String, pass: String): TokenResponse
}

class UserDao {
    suspend fun saveUser(user: UserEntity)
    suspend fun getUser(id: Long): UserEntity?
}

class AnalyticsTracker {
    fun track(event: String, params: Map)
}

// Facade — رابط ساده برای UI
class AuthService(
    private val api: AuthApi,
    private val dao: UserDao,
    private val analytics: AnalyticsTracker
) {
    suspend fun loginUser(email: String, password: String): Result {
        return runCatching {
            val token = api.login(email, password)
            val user = User(token.userId, email, token.accessToken)
            dao.saveUser(user.toEntity())
            analytics.track("login_success", mapOf("method" to "email"))
            user
        }
    }
}

AuthService — یک Facade که AuthApi، UserDao و AnalyticsTracker را از ViewModel پنهان می‌کند. UI به‌جای سه درخواست جداگانه به API، پایگاه داده و تحلیل، loginUser(email, password) را فراخوانی می‌کند. این کار اتصال را کاهش می‌دهد: اگر فردا AuthApi به FirebaseAuth تبدیل شود یا UserDao به Room مهاجرت کند، فقط Facade تغییر می‌کند، نه UI.

Facade در معماری موبایل: Service Layer

Service Layer — پیاده‌سازی رایج Facade در برنامه‌های موبایل. این لایه منطق تجاری و هماهنگی بین لایه‌ها را کپسوله می‌کند. در Android، Service Layer اغلب از طریق UseCase (Clean Architecture) پیاده‌سازی می‌شود و در iOS از طریق Manager یا پروتکل‌های Service.

مؤلفهنقش در زیرسیستمFacade چه چیزی را پنهان می‌کند
AuthApiدرخواست شبکه به سرورفرمت درخواست، endpoint، مدیریت خطاهای HTTP
UserDaoذخیره‌سازی محلی توکنطرح پایگاه داده، کوئری‌های SQL، مهاجرت‌ها
AnalyticsTrackerارسال رویدادهای تحلیلSDK Firebase/AppMetrica، فرمت رویدادها
NetworkMonitorبررسی دسترسی به شبکهConnectivityManager، BroadcastReceiver

AuthService هر چهار مؤلفه را ترکیب می‌کند. ViewModel یک متد را فراخوانی می‌کند بدون اینکه بداند زیر کاپوت یک درخواست شبکه، نوشتن در پایگاه داده، ردیابی و بررسی شبکه انجام می‌شود. هنگام تست، AuthService را می‌توان با mock جایگزین کرد و کل منطق احراز هویت را بدون یکپارچه‌سازی با مؤلفه‌های واقعی بررسی کرد.

Facade در برابر Adapter در برابر Mediator

Facade، Adapter و Mediator — الگوهای ساختاری هستند اما مسائل مختلفی را حل می‌کنند. اغلب با هم اشتباه گرفته می‌شوند، چون هر سه یک شیء واسطه معرفی می‌کنند. تفاوت‌ها را با مثال یک برنامه موبایل بررسی می‌کنیم.

جنبهFacadeAdapterMediator
هدفساده‌کردن رابط زیرسیستمتبدیل رابطکاهش اتصال مؤلفه‌ها
جهتیک رابط → زیرسیستمکلاینت → AdapteeN مؤلفه ↔ Mediator
تغییر رابطجدید و ساده‌شده می‌سازدموجود را تبدیل می‌کندتغییر نمی‌دهد، هماهنگ می‌کند
آیا زیرسیستم از الگو خبر دارد؟خیرخیربله، از طریق Mediator ارتباط برقرار می‌کند
نمونه در توسعه موبایلUseCase / Service LayerRecyclerView.AdapterCoordinator در iOS

Facade زیرسیستم را پنهان نمی‌کند — کلاینت در صورت نیاز می‌تواند مستقیماً به AuthApi دسترسی داشته باشد. Adapter حتماً رابط Adaptee را تغییر می‌دهد. Mediator تعاملات پیچیده بین بسیاری از اشیایی را که ممکن است از یکدیگر بی‌خبر باشند هماهنگ می‌کند.

پیاده‌سازی Facade در Kotlin برای Android

پیاده‌سازی Facade در Kotlin برای Android با Clean Architecture از UseCase به‌عنوان نقطه ورود برای هر سناریوی تجاری استفاده می‌کند. UseCase یک Facade است که مخزن، مپر و سایر وابستگی‌ها را از لایه UI پنهان می‌کند.

Kotlin
// Repository — هم Facade است، اما یک سطح پایین‌تر
class UserRepositoryImpl(
    private val local: UserLocalDataSource,
    private val remote: UserRemoteDataSource,
    private val mapper: UserMapper
) : UserRepository {
    override suspend fun getUserProfile(id: String): UserProfile {
        val cached = local.getUser(id)
        if (cached != null && !cached.isStale) {
            return mapper.toProfile(cached)
        }
        val dto = remote.fetchUser(id)
        val entity = mapper.toEntity(dto)
        local.saveUser(entity)
        return mapper.toProfile(entity)
    }
}

// UseCase — Facade برای سناریوی تجاری
class LoadUserProfileUseCase(
    private val repo: UserRepository,
    private val analytics: AnalyticsTracker
) {
    suspend operator fun invoke(userId: String): Result {
        return runCatching {
            val profile = repo.getUserProfile(userId)
            analytics.track("profile_loaded", mapOf("user_id" to userId))
            profile
        }
    }
}

LoadUserProfileUseCase — Facade برای سناریوی بارگذاری پروفایل. این الگو منطق کش‌کردن (local → remote)، نگاشت DTO → Entity → Profile و ردیابی تحلیل را پنهان می‌کند. ViewModel invoke(userId) را فراخوانی می‌کند و UserProfile آماده یا یک خطا دریافت می‌کند. UseCase را می‌توان به‌صورت ایزوله با جایگزین‌کردن مخزن با شیء mock تست کرد.

پیاده‌سازی Facade در Swift برای iOS

Facade در iOS اغلب به‌صورت Manager یا Service پیاده‌سازی می‌شود. برخلاف Android، iOS برای تعریف رابط Facade از پروتکل‌ها استفاده می‌کند که جایگزینی پیاده‌سازی‌ها در تست‌ها را آسان می‌کند. یک Facade برای کار با رسانه را بررسی می‌کنیم — بارگذاری، کش‌کردن و نمایش.

Swift
protocol MediaServiceProtocol {
    func loadImage(from url: URL) async -> Result<UIImage, Error>
}

final class MediaService: MediaServiceProtocol {
    private let cache: ImageCache
    private let downloader: ImageDownloader
    private let decoder: ImageDecoder
    
    func loadImage(from url: URL) async -> Result<UIImage, Error> {
        // ۱. بررسی کش
        if let cached = cache.image(for: url) {
            return .success(cached)
        }
        // ۲. بارگذاری داده
        let result = await downloader.download(from: url)
        guard case let .success(data) = result else {
            return .failure(MediaError.downloadFailed)
        }
        // ۳. رمزگشایی
        guard let image = decoder.decode(data) else {
            return .failure(MediaError.decodeFailed)
        }
        // ۴. ذخیره در کش
        cache.setImage(image, for: url)
        return .success(image)
    }
}

MediaService فرآیند سه‌مرحله‌ای را کپسوله می‌کند: کش → بارگذاری → رمزگشایی. UI به‌جای مدیریت ImageCache، URLSession و ImageDecoder یک متد loadImage(from:) را فراخوانی می‌کند. در تست می‌توان MediaServiceProtocol را با mockی جایگزین کرد که تصاویر ازپیش‌تنظیم‌شده را بدون بارگذاری واقعی برمی‌گرداند.

اشتباهات رایج در استفاده از Facade

اشتباهات در طراحی Facade مزایای آن را از بین می‌برند: به‌جای ساده‌سازی، God Object به‌وجود می‌آید که کل سیستم به آن وابسته است. سه مشکل اصلی را بررسی می‌کنیم.

God Facade — مسئولیت بیش از حد

هنگامی که یک Facade حاوی متدهایی برای احراز هویت، بارگذاری پروفایل، ارسال پیام و همگام‌سازی است — این یک God Object است. نشانه: بیش از ۱۵ متد عمومی در یک کلاس. راه‌حل: تقسیم به چند Facade تخصصی بر اساس حوزه‌های مسئولیت — AuthService، ProfileService، MessagingService.

Facade با نشت جزئیات زیرسیستم

اگر Facade انواع خاص زیرسیستم را برمی‌گرداند (مثلاً FirebaseUser یا RealmObject)، کلاینت همچنان به یک پیاده‌سازی خاص وابسته است. راه‌حل: Facade باید فقط انواع خودش (data class / struct) را برگرداند و کلاینت را کاملاً از جزئیات زیرسیستم انتزاع کند.

Facade به‌عنوان تنها نقطه ورود

هنگامی که Facade دسترسی مستقیم به زیرسیستم را ممنوع می‌کند، به تنگنا تبدیل می‌شود. گاهی کلاینت به یک متد خاص زیرسیستم نیاز دارد و مجبورکردن او به عبور از Facade زائد است. Facade نباید gatekeeper سخت‌گیر باشد: رابط راحتی ارائه می‌دهد، اما دسترسی مستقیم به مؤلفه‌ها را مسدود نمی‌کند.

سؤالات متداول

تفاوت بین Facade و Proxy چیست؟

Facade رابط ساده‌شده‌ای به زیرسیستم ارائه می‌دهد و اغلب مجموعه‌ای جدید از متدها می‌سازد. Proxy همان رابط شیء اصلی را حفظ می‌کند، اما کنترل دسترسی یا بارگذاری تنبل اضافه می‌کند. Facade برای ساده‌سازی است، Proxy برای کنترل.

آیا Facade همان Service Layer است؟

Service Layer — پیاده‌سازی الگوی Facade در سطح معماری برنامه است. این لایه مرز بین UI و منطق تجاری را تعریف می‌کند و جزئیات پیاده‌سازی سرویس‌ها را پنهان می‌کند. در Android، Service Layer اغلب از طریق UseCase و در iOS از طریق Manager یا پروتکل‌های Service پیاده‌سازی می‌شود.

چه زمانی Facade به God Object تبدیل می‌شود؟

God Facade زمانی به‌وجود می‌آید که یک کلاس مسئولیت چندین زیرسیستم نامرتبط را بر عهده می‌گیرد. نشانه‌ها: بیش از ۱۵ متد عمومی، متدهایی از حوزه‌های مختلف (احراز هویت + پرداخت + اعلان‌ها)، کلاسی که تست آن دشوار است (بیش از ۱۰ وابستگی). راه‌حل: تقسیم به Facadeهای دامنه‌ای.

آیا Facade در برنامه کوچک لازم است؟

در برنامه‌ای با ۱-۲ صفحه، Facade زائد است — فراخوانی مستقیم API و پایگاه داده از UI ساده‌تر و واضح‌تر است. Facade به‌صرفه است با بیش از ۵ صفحه و بیش از ۳ زیرسیستم. در پروژه‌های متوسط و کوچک، Repository به‌عنوان تنها لایه Facade بدون پوسته اضافی UseCase کافی است.

چگونه کدی که از Facade استفاده می‌کند را تست کنیم؟

Facade تست را ساده می‌کند، زیرا کل زیرسیستم را با یک شیء mock جایگزین می‌کند. به‌جای mock سه مؤلفه (شبکه + پایگاه داده + تحلیل)، mock یک Facade کافی است. در Swift برای این کار از protocol و در Kotlin از interface استفاده می‌شود. Facade برای تست‌های یکپارچه‌سازی که ارکستراسیون مؤلفه‌ها را بررسی می‌کنند نیز مناسب است.

خلاصه

  • Facade — الگوی ساختاری که رابطی ساده به زیرسیستم پیچیده ارائه می‌دهد
  • Service Layer و UseCase — پیاده‌سازی‌های رایج Facade در معماری موبایل
  • Facade زیرسیستم را پنهان نمی‌کند: کلاینت در صورت نیاز می‌تواند مستقیماً به مؤلفه‌ها دسترسی داشته باشد
  • Facade در برابر Adapter: Facade ساده می‌کند، Adapter تبدیل می‌کند؛ Facade در برابر Mediator: Facade یک‌طرفه است، Mediator دوجانبه
  • God Facade — ضدالگو: بیش از ۱۵ متد در یک کلاس نشان‌دهنده نقض Single Responsibility است
  • پروتکل/رابط برای Facade ضروری است — تنها راه تست mock زیرسیستم
  • توصیه: Facade را با بیش از ۵ صفحه و بیش از ۳ زیرسیستم معرفی کنید؛ برای پروژه‌های کوچک Repository کافی است

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید