Facade ay isang istruktural na pattern ng disenyo na nagbibigay ng pinasimpleng interface sa isang kumplikadong subsystem ng mga klase. Sa mobile development, ang Facade ay kadalasang ipinapatupad bilang Service Layer o UseCase, na nagtatago ng interaksyon sa network, database, at analytics. Ayon kay Martin Fowler (Patterns of Enterprise Application Architecture, 2003), ang Facade ay isa sa mga pangunahing pattern para sa pag-oorganisa ng layer ng serbisyo.
Mga pangunahing punto
Facade — istruktural na pattern na nagbibigay ng pinag-isang interface sa isang grupo ng mga interface ng subsystem. Tinutukoy nito ang isang interface sa mataas na antas na nagpapasimple sa paggamit ng subsystem. Hindi nagdaragdag ng bagong functionality ang Facade — inoorkestra nito ang mga umiiral na component at itinatago ang pagiging kumplikado ng kanilang interaksyon mula sa kliyente.
// Kumplikadong subsystem
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 — simpleng interface para sa 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 na nagtatago ng AuthApi, UserDao, at AnalyticsTracker mula sa ViewModel. Tumatawag ang UI ng loginUser(email, password) sa halip na tatlong hiwalay na kahilingan sa API, database, at analytics. Binabawasan nito ang coupling: kung bukas ay magiging FirebaseAuth ang AuthApi o magmi-migrate ang UserDao sa Room, ang Facade lamang ang magbabago, hindi ang UI.
Service Layer — karaniwang pagpapatupad ng Facade sa mga mobile application. Ine-encapsulate nito ang business logic at ang koordinasyon sa pagitan ng mga layer. Sa Android, ang Service Layer ay kadalasang ipinapatupad sa pamamagitan ng UseCase (Clean Architecture), sa iOS — sa pamamagitan ng Manager o mga Service protocol.
| Component | Papel sa subsystem | Ano ang itinatago ng Facade |
|---|---|---|
| AuthApi | Network request sa server | Format ng kahilingan, endpoint, paghawak ng mga error sa HTTP |
| UserDao | Lokal na pag-iimbak ng token | Schema ng database, mga SQL query, migrasyon |
| AnalyticsTracker | Paghahatid ng mga event ng analytics | Firebase/AppMetrica SDK, format ng mga event |
| NetworkMonitor | Pagsusuri ng availability ng network | ConnectivityManager, BroadcastReceiver |
AuthService pinag-iisa ang lahat ng apat na component. Tumatawag ang ViewModel ng isang method, nang hindi nalalaman na sa ilalim ng hood ay nangyayari ang isang network request, pagsulat sa database, tracking, at pagsusuri ng network. Sa pag-test, maaaring palitan ang AuthService ng mock, na sinusuri ang buong lohika ng pagpapatotoo nang walang integrasyon sa mga totoong component.
Facade, Adapter, at Mediator — mga istruktural na pattern, ngunit nilulutas nila ang iba't ibang problema. Madalas silang napagkakamalan, dahil lahat ng tatlo ay nagpapakilala ng isang tagapamagitang object. Tingnan natin ang mga pagkakaiba gamit ang halimbawa ng isang mobile application.
| Aspekto | Facade | Adapter | Mediator |
|---|---|---|---|
| Layunin | Pasimplehin ang interface ng subsystem | Palitan ang interface | Bawasan ang coupling ng mga component |
| Direksyon | Isang interface → subsystem | Kliyente → Adaptee | N component ↔ Mediator |
| Pagbabago ng interface | Lumilikha ng bago, pinasimple | Pinapalitan ang umiiral | Hindi binabago, kinoordina |
| Alam ba ng subsystem ang pattern? | Hindi | Hindi | Oo, nakikipag-ugnayan sa pamamagitan ng Mediator |
| Halimbawa sa mobile development | UseCase / Service Layer | RecyclerView.Adapter | Coordinator sa iOS |
Facade ay hindi itinatago ang subsystem — maaaring direktang ma-access ng kliyente ang AuthApi kung kinakailangan. Adapter ay sapilitang binabago ang interface ng Adaptee. Mediator ay kinoordina ang mga kumplikadong interaksyon sa pagitan ng maraming object na maaaring hindi kilala ang isa't isa.
Ang pagpapatupad ng Facade sa Kotlin para sa Android na may Clean Architecture ay gumagamit ng UseCase bilang entry point para sa bawat business scenario. Ang UseCase ay isang Facade na nagtatago ng repository, mapper, at iba pang dependencies mula sa UI layer.
// Repository — Facade din, ngunit isang antas na mas mababa
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 para sa business scenario
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 para sa scenario ng pag-load ng profile. Itinatago nito ang lohika ng caching (local → remote), ang pagmamapa ng DTO → Entity → Profile, at ang pagsubaybay ng analytics. Tumatawag ang ViewModel ng invoke(userId) at tumatanggap ng handa nang UserProfile o isang error. Maaaring i-test ang UseCase nang nakahiwalay sa pamamagitan ng pagpapalit ng repository ng mock object.
Ang Facade sa iOS ay kadalasang ipinapatupad bilang Manager o Service. Hindi tulad ng Android, gumagamit ang iOS ng mga protocol upang tukuyin ang interface ng Facade, na ginagawang madali ang pagpapalit ng mga pagpapatupad sa mga test. Tingnan natin ang isang Facade para sa pagtatrabaho sa media — pag-load, pag-cache, at pagpapakita.
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. Suriin ang cache
if let cached = cache.image(for: url) {
return .success(cached)
}
// 2. I-load ang data
let result = await downloader.download(from: url)
guard case let .success(data) = result else {
return .failure(MediaError.downloadFailed)
}
// 3. I-decode
guard let image = decoder.decode(data) else {
return .failure(MediaError.decodeFailed)
}
// 4. I-save sa cache
cache.setImage(image, for: url)
return .success(image)
}
}MediaService ay ine-encapsulate ang isang proseso na may tatlong hakbang: cache → pag-load → pag-decode. Tumatawag ang UI ng isang method na loadImage(from:) sa halip na pamahalaan ang ImageCache, URLSession, at ImageDecoder. Sa pag-test, maaaring palitan ang MediaServiceProtocol ng mock na nagbabalik ng mga itinakdang imahe nang walang totoong pag-load.
Ang mga pagkakamali sa pagdidisenyo ng Facade ay sumisira sa mga bentahe nito: sa halip na pagpapasimple, lumilitaw ang isang God Object na pinagkakatiwalaan ng buong sistema. Tingnan natin ang tatlong pangunahing problema.
Kapag ang isang Facade ay naglalaman ng mga method para sa pagpapatotoo, pag-load ng profile, pagpapadala ng mensahe, at pag-sync — ito ay isang God Object. Tanda: higit sa 15 pampublikong method sa isang klase. Solusyon: hatiin sa ilang espesyalisadong Facade ayon sa mga lugar ng responsibilidad — AuthService, ProfileService, MessagingService.
Kung ang Facade ay nagbabalik ng mga type na tiyak sa subsystem (halimbawa, FirebaseUser o RealmObject), ang kliyente ay nakatali pa rin sa isang partikular na pagpapatupad. Solusyon: ang Facade ay dapat magbalik lamang ng sarili nitong mga type (data class / struct), na ganap na ina-abstrakta ang kliyente mula sa mga detalye ng subsystem.
Kapag ipinagbabawal ng Facade ang direktang pag-access sa subsystem, ito ay nagiging bottleneck. Minsan kailangan ng kliyente ang isang partikular na method ng subsystem, at ang pagpilit sa kanya na dumaan sa Facade ay labis. Ang Facade ay hindi dapat maging mahigpit na gatekeeper: nagbibigay ito ng maginhawang interface, ngunit hindi hinaharangan ang direktang pag-access sa mga component.
Mga madalas itanong
Facade ay nagbibigay ng pinasimpleng interface sa subsystem, madalas na lumilikha ng bagong hanay ng mga method. Proxy ay pinapanatili ang parehong interface ng orihinal na object, ngunit nagdaragdag ng kontrol sa pag-access o lazy loading. Facade — para sa pagpapasimple, Proxy — para sa kontrol.
Service Layer — ito ang pagpapatupad ng pattern ng Facade sa antas ng arkitektura ng application. Tinutukoy nito ang hangganan sa pagitan ng UI at ng business logic, itinatago ang mga detalye ng pagpapatupad ng mga serbisyo. Sa Android, ang Service Layer ay kadalasang ipinapatupad sa pamamagitan ng UseCase, sa iOS — sa pamamagitan ng Manager o mga Service protocol.
God Facade ay lumilitaw kapag ang isang klase ay kumukuha ng responsibilidad para sa ilang hindi magkaugnay na subsystem. Tanda: higit sa 15 pampublikong method, mga method mula sa iba't ibang domain (pagpapatotoo + pagbabayad + mga notification), isang klase na mahirap i-test (higit sa 10 dependencies). Solusyon: hatiin sa mga Facade ayon sa domain.
Sa isang application na may 1-2 screen, ang Facade ay labis — ang direktang pagtawag ng API at database mula sa UI ay mas simple at mas malinaw. Nagbabayad ang Facade sa higit sa 5 screen at higit sa 3 subsystem. Sa mga katamtaman at maliliit na proyekto, sapat na ang Repository bilang nag-iisang layer ng Facade, nang walang dagdag na wrapper ng UseCase.
Pinapasimple ng Facade ang pag-test, dahil pinapalitan nito ang buong subsystem ng isang mock object. Sa halip na i-mock ang tatlong component (network + database + analytics), sapat na ang i-mock ang isang Facade. Sa Swift para dito ay ginagamit ang protocol, sa Kotlin — ang interface. Ang Facade ay maginhawa rin para sa integration test, kung saan sinusuri ang orkestrasyon ng mga component.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din