Facade: fundamentos do padrão fachada na arquitetura móvel

Autor: IT Sectr Publicado: 2026-02-18 Tempo de leitura: 9 min

Facade é um padrão de projeto estrutural que fornece uma interface simplificada para um subsistema complexo de classes. No desenvolvimento móvel, o Facade é mais frequentemente implementado como Service Layer ou UseCase, ocultando a interação com a rede, o banco de dados e a análise. Segundo Martin Fowler (Patterns of Enterprise Application Architecture, 2003), o Facade é um dos padrões-chave para organizar a camada de serviços.

O essencial

  • Facade — padrão estrutural que fornece uma interface simples para um sistema complexo de classes, bibliotecas ou frameworks
  • Service Layer — implementação do Facade na arquitetura móvel que oculta API, cache e análise da UI
  • Facade não oculta o subsistema — o cliente pode acessá-lo diretamente quando necessário
  • UseCase na Clean Architecture — uma variação do Facade que orquestra um único cenário de negócio
  • Facade vs Adapter: o Facade simplifica a interface, o Adapter transforma uma interface em outra

O que é o padrão Facade?

Facade é um padrão estrutural que fornece uma interface unificada para um grupo de interfaces do subsistema. Ele define uma interface de alto nível que simplifica o uso do subsistema. O Facade não adiciona nova funcionalidade — ele orquestra os componentes existentes, ocultando a complexidade da sua interação do cliente.

Kotlin
// Subsistema complexo
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 — uma interface simples para a 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 é um Facade que oculta AuthApi, UserDao e AnalyticsTracker do ViewModel. A UI chama loginUser(email, password) em vez de três requisições separadas à API, ao banco de dados e à análise. Isso reduz o acoplamento: se amanhã AuthApi virar FirebaseAuth ou UserDao migrar para Room, apenas o Facade muda, não a UI.

Facade na arquitetura móvel: Service Layer

Service Layer é uma implementação comum do Facade em aplicativos móveis. Ele encapsula a lógica de negócio e a coordenação entre camadas. No Android, o Service Layer é frequentemente implementado via UseCase (Clean Architecture), e no iOS via protocolos Manager ou Service.

Componente Papel no subsistema O que o Facade oculta
AuthApi Requisição de rede ao servidor Formato da requisição, endpoint, tratamento de erros HTTP
UserDao Armazenamento local do token Esquema do banco de dados, consultas SQL, migrações
AnalyticsTracker Envio de eventos de análise SDK Firebase/AppMetrica, formato de eventos
NetworkMonitor Verificação da disponibilidade de rede ConnectivityManager, BroadcastReceiver

AuthService combina todos os quatro componentes. O ViewModel chama um único método sem saber que, por baixo dos panos, acontecem requisição de rede, escrita no banco, rastreamento e verificação de rede. Ao testar, o AuthService pode ser substituído por um mock, verificando toda a lógica de autenticação sem integração com componentes reais.

Facade vs Adapter vs Mediator

Facade, Adapter e Mediator são padrões estruturais, mas resolvem problemas diferentes. Eles são frequentemente confundidos, pois os três introduzem um objeto intermediário. Vamos analisar as diferenças usando um aplicativo móvel como exemplo.

Aspecto Facade Adapter Mediator
Objetivo Simplificar a interface do subsistema Transformar uma interface Reduzir o acoplamento entre componentes
Direção Uma interface → subsistema Cliente → Adaptee N componentes ↔ Mediator
Mudança de interface Cria uma nova, simplificada Transforma a existente Não muda, coordena
O subsistema conhece o padrão? Não Não Sim, comunica-se através do Mediator
Exemplo no desenvolvimento móvel UseCase / Service Layer RecyclerView.Adapter Coordinator no iOS

Facade não oculta o subsistema — o cliente pode acessar o AuthApi diretamente quando necessário. Adapter obrigatoriamente muda a interface do Adaptee. Mediator coordena interações complexas entre muitos objetos que podem não se conhecer.

Implementação do Facade em Kotlin para Android

A implementação do Facade em Kotlin para Android com Clean Architecture usa UseCase como ponto de entrada para cada cenário de negócio. UseCase é um Facade que oculta o repositório, o mapper e outras dependências da camada de UI.

Kotlin
// Repository também é um Facade, mas em nível inferior
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 — um Facade para o cenário de negócio
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 é um Facade para o cenário de carregamento de perfil. Ele oculta a lógica de cache (local → remoto), o mapeamento DTO → Entity → Profile e o rastreamento de análise. O ViewModel chama invoke(userId) e recebe um UserProfile pronto ou um erro. O UseCase pode ser testado isoladamente, substituindo o repositório por um objeto mock.

Implementação do Facade em Swift para iOS

Facade no iOS é frequentemente implementado como Manager ou Service. Ao contrário do Android, o iOS usa protocolos para definir a interface do Facade, o que permite trocar facilmente as implementações nos testes. Vamos ver um Facade para trabalhar com mídia — carregamento, cache e exibição.

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> {
        // 1. Verificar o cache
        if let cached = cache.image(for: url) {
            return .success(cached)
        }
        // 2. Carregar os dados
        let result = await downloader.download(from: url)
        guard case let .success(data) = result else {
            return .failure(MediaError.downloadFailed)
        }
        // 3. Decodificar
        guard let image = decoder.decode(data) else {
            return .failure(MediaError.decodeFailed)
        }
        // 4. Salvar no cache
        cache.setImage(image, for: url)
        return .success(image)
    }
}

MediaService encapsula um processo de três etapas: cache → carregamento → decodificação. A UI chama um único método loadImage(from:) em vez de gerenciar ImageCache, URLSession e ImageDecoder. Ao testar, MediaServiceProtocol pode ser substituído por um mock que retorna imagens predefinidas sem carregamento real.

Erros típicos ao usar o Facade

Os erros no projeto do Facade anulam suas vantagens: em vez de simplificação, você obtém um God Object do qual todo o sistema depende. Vamos analisar os três principais problemas.

God Facade — responsabilidade demais

Quando um único Facade contém métodos para autenticação, carregamento de perfil, envio de mensagens e sincronização — isso é um God Object. Sinal: mais de 15 métodos públicos em uma classe. Solução: dividir em vários Facades especializados por áreas de responsabilidade — AuthService, ProfileService, MessagingService.

Facade com vazamento de detalhes do subsistema

Se o Facade retorna tipos específicos do subsistema (por exemplo, FirebaseUser ou RealmObject), o cliente ainda fica preso a uma implementação concreta. Solução: o Facade deve retornar apenas seus próprios tipos (data class / struct), abstraindo totalmente o cliente dos detalhes do subsistema.

Facade como único ponto de entrada

Quando o Facade proíbe o acesso direto ao subsistema, ele se torna um gargalo. Às vezes o cliente precisa de um método específico do subsistema, e forçá-lo a passar pelo Facade é redundante. Facade não deve ser um gatekeeper rígido: ele fornece uma interface conveniente, mas não bloqueia o acesso direto aos componentes.

Perguntas frequentes

Qual é a diferença entre Facade e Proxy?

Facade fornece uma interface simplificada ao subsistema, frequentemente criando um novo conjunto de métodos. Proxy mantém a mesma interface do objeto original, mas adiciona controle de acesso ou carregamento preguiçoso. Facade é para simplificar, Proxy é para controlar.

Facade é o mesmo que Service Layer?

Service Layer é uma implementação do padrão Facade no nível da arquitetura do aplicativo. Ele define a fronteira entre a UI e a lógica de negócio, ocultando os detalhes de implementação dos serviços. No Android, o Service Layer é frequentemente implementado via UseCase; no iOS, via protocolos Manager ou Service.

Quando o Facade vira um God Object?

God Facade surge quando uma classe assume a responsabilidade por vários subsistemas não relacionados. Sinais: mais de 15 métodos públicos, métodos de domínios diferentes (autenticação + pagamentos + notificações), uma classe difícil de testar (mais de 10 dependências). Solução: dividir em Facades de domínio.

Facade é necessário em um aplicativo pequeno?

Em um aplicativo com 1-2 telas, o Facade é redundante — chamar a API e o banco de dados diretamente da UI é mais simples e claro. O Facade compensa com 5+ telas e 3+ subsistemas. Em projetos pequenos e médios, um Repository como única camada Facade é suficiente, sem envoltório adicional de UseCase.

Como testar código que usa Facade?

Facade simplifica os testes, pois substitui todo um subsistema por um único objeto mock. Em vez de simular três componentes (rede + banco de dados + análise), basta simular um Facade. Em Swift, protocolos são usados para isso; em Kotlin, interfaces. O Facade também é conveniente para testes de integração que verificam a orquestração de componentes.

Resumo

  • Facade — padrão estrutural que fornece uma interface simples para um subsistema complexo
  • Service Layer e UseCase — implementações comuns do Facade na arquitetura móvel
  • Facade não oculta o subsistema: o cliente pode acessar os componentes diretamente quando necessário
  • Facade vs Adapter: Facade simplifica, Adapter transforma; Facade vs Mediator: Facade é unidirecional, Mediator é bidirecional
  • God Facade — antipadrão: mais de 15 métodos em uma classe sinalizam a violação do Single Responsibility
  • Protocolo/interface para Facade é obrigatório — é a única forma de testar o subsistema com mocks
  • Recomendação: introduza o Facade com 5+ telas e 3+ subsistemas; para projetos pequenos, Repository é suficiente

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também