Facade: พื้นฐานของแพทเทิร์น Facade ในสถาปัตยกรรมโมบาย

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-02-18 เวลาอ่าน: 9 นาที

Facade เป็นแพทเทิร์นการออกแบบเชิงโครงสร้าง (structural design pattern) ที่ให้อินเทอร์เฟซที่เรียบง่ายสำหรับระบบย่อยของคลาสที่ซับซ้อน ในการพัฒนาโมบาย 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 เรียกใช้ loginUser(email, password) แทนการส่งคำขอแยกกันสามคำขอไปยัง API ฐานข้อมูล และระบบวิเคราะห์ข้อมูล สิ่งนี้ลดการผูกโยง: ถ้าพรุ่งนี้ 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 การส่งอีเวนต์การวิเคราะห์ Firebase/AppMetrica SDK รูปแบบอีเวนต์
NetworkMonitor การตรวจสอบความพร้อมใช้งานของเครือข่าย ConnectivityManager, BroadcastReceiver

AuthService รวมส่วนประกอบทั้งสี่เข้าด้วยกัน ViewModel เรียกใช้เมธอดหนึ่งเมธอดโดยไม่รู้ว่าเบื้องหลังมีการส่งคำขอเครือข่าย การเขียนฐานข้อมูล การติดตาม และการตรวจสอบเครือข่าย เมื่อทดสอบ สามารถแทนที่ AuthService ด้วย mock เพื่อตรวจสอบตรรกะการยืนยันตัวตนทั้งหมดโดยไม่ต้องบูรณาการกับส่วนประกอบจริง

Facade เทียบกับ Adapter เทียบกับ Mediator

Facade, Adapter และ Mediator เป็นแพทเทิร์นเชิงโครงสร้าง แต่แก้ปัญหาที่แตกต่างกัน พวกมันมักถูกสับสนเพราะทั้งสามต่างก็แนะนำวัตถุตัวกลาง มาวิเคราะห์ความแตกต่างด้วยตัวอย่างแอปพลิเคชันโมบายกัน

ด้าน Facade Adapter Mediator
วัตถุประสงค์ ทำให้อินเทอร์เฟซระบบย่อยง่ายขึ้น แปลงอินเทอร์เฟซ ลดการผูกโยงระหว่างส่วนประกอบ
ทิศทาง หนึ่งอินเทอร์เฟซ → ระบบย่อย ไคลเอนต์ → Adaptee N ส่วนประกอบ ↔ Mediator
การเปลี่ยนอินเทอร์เฟซ สร้างใหม่ที่เรียบง่าย แปลงอินเทอร์เฟซที่มีอยู่ ไม่เปลี่ยน แต่ประสานงาน
ระบบย่อยรู้จักแพทเทิร์นหรือไม่? ไม่ ไม่ ใช่ สื่อสารผ่าน Mediator
ตัวอย่างในการพัฒนาโมบาย UseCase / Service Layer RecyclerView.Adapter Coordinator ใน iOS

Facade ไม่ได้ซ่อนระบบย่อย — ไคลเอนต์สามารถเข้าถึง AuthApi ได้โดยตรงเมื่อจำเป็น Adapter จำเป็นต้องเปลี่ยนอินเทอร์เฟซของ Adaptee Mediator ประสานงานการโต้ตอบที่ซับซ้อนระหว่างวัตถุจำนวนมากที่อาจไม่รู้จักกันและกัน

การนำ Facade ไปใช้ใน Kotlin สำหรับ Android

การนำ Facade ไปใช้ ใน Kotlin สำหรับ Android ด้วย Clean Architecture ใช้ UseCase เป็นจุดเข้าสำหรับแต่ละสถานการณ์ธุรกิจ UseCase คือ Facade ที่ซ่อน repository mapper และการพึ่งพาอื่น ๆ จากชั้น 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 แบบแยกส่วนได้โดยการแทนที่ repository ด้วยวัตถุ 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> {
        // 1. ตรวจสอบแคช
        if let cached = cache.image(for: url) {
            return .success(cached)
        }
        // 2. โหลดข้อมูล
        let result = await downloader.download(from: url)
        guard case let .success(data) = result else {
            return .failure(MediaError.downloadFailed)
        }
        // 3. ถอดรหัส
        guard let image = decoder.decode(data) else {
            return .failure(MediaError.decodeFailed)
        }
        // 4. บันทึกลงแคช
        cache.setImage(image, for: url)
        return .success(image)
    }
}

MediaService ห่อหุ้มกระบวนการสามขั้นตอน: แคช → โหลด → ถอดรหัส UI เรียกใช้เมธอดเดียว loadImage(from:) แทนการจัดการ ImageCache, URLSession และ ImageDecoder เมื่อทดสอบ สามารถแทนที่ MediaServiceProtocol ด้วย mock ที่คืนรูปภาพที่กำหนดไว้ล่วงหน้าโดยไม่ต้องโหลดจริง

ข้อผิดพลาดทั่วไปเมื่อใช้ Facade

ข้อผิดพลาด ในการออกแบบ Facade ทำให้ข้อดีของมันไร้ประโยชน์: แทนที่จะง่ายขึ้น คุณกลับได้ God Object ที่ทั้งระบบต้องพึ่งพา มาวิเคราะห์ปัญหาหลักสามข้อกัน

God Facade — ความรับผิดชอบมากเกินไป

เมื่อ Facade เดียวมีเมธอดสำหรับการยืนยันตัวตน การโหลดโปรไฟล์ การส่งข้อความ และการซิงโครไนซ์ — นี่คือ God Object สัญญาณ: มีเมธอดสาธารณะมากกว่า 15 เมธอดในคลาสเดียว วิธีแก้: แบ่งเป็น Facade เฉพาะทางหลายตัวตามขอบเขตความรับผิดชอบ — AuthService, ProfileService, MessagingService

Facade ที่รั่วไหลรายละเอียดของระบบย่อย

ถ้า Facade คืนประเภทที่เฉพาะเจาะจงกับระบบย่อย (เช่น FirebaseUser หรือ RealmObject) ไคลเอนต์ก็ยังผูกติดกับการนำไปใช้แบบเฉพาะเจาะจง วิธีแก้: Facade ควรคืนเฉพาะประเภทของตัวเอง (data class / struct) โดยแยกไคลเอนต์ออกจากรายละเอียดของระบบย่อยอย่างสมบูรณ์

Facade เป็นจุดเข้าจุดเดียว

เมื่อ Facade ห้ามการเข้าถึงระบบย่อยโดยตรง มันกลายเป็นคอขวด บางครั้งไคลเอนต์ต้องการเมธอดเฉพาะของระบบย่อย และการบังคับให้มันผ่าน Facade ก็เกินจำเป็น Facade ไม่ควรเป็นผู้เฝ้าประตูที่เข้มงวด: มันให้อินเทอร์เฟซที่สะดวก แต่ไม่ได้ปิดกั้นการเข้าถึงส่วนประกอบโดยตรง

คำถามที่พบบ่อย

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 เกิดขึ้นเมื่อคลาสหนึ่งรับผิดชอบระบบย่อยหลายระบบที่ไม่เกี่ยวข้องกัน สัญญาณ: มีเมธอดสาธารณะมากกว่า 15 เมธอด เมธอดจากโดเมนต่าง ๆ (การยืนยันตัวตน + การชำระเงิน + การแจ้งเตือน) คลาสที่ทดสอบยาก (มีการพึ่งพามากกว่า 10 รายการ) วิธีแก้: แบ่งเป็น Facade ตามโดเมน

แอปพลิเคชันเล็กจำเป็นต้องมี Facade หรือไม่?

ในแอปพลิเคชันที่มี 1-2 หน้าจอ Facade เกินจำเป็น — การเรียก API และฐานข้อมูลโดยตรงจาก UI นั้นง่ายและชัดเจนกว่า Facade คุ้มค่า เมื่อมี 5+ หน้าจอและ 3+ ระบบย่อย ในโปรเจกต์ขนาดเล็กและขนาดกลาง Repository เดียวเป็นชั้น Facade ก็เพียงพอแล้ว โดยไม่ต้องใช้ UseCase wrapper เพิ่มเติม

จะทดสอบโค้ดที่ใช้ Facade ได้อย่างไร?

Facade ทำให้การทดสอบง่ายขึ้น เพราะมันแทนที่ระบบย่อยทั้งหมดด้วยวัตถุ mock เดียว แทนที่จะ mock สามส่วนประกอบ (เครือข่าย + ฐานข้อมูล + การวิเคราะห์) แค่ mock Facade ตัวเดียวก็เพียงพอ ใน Swift ใช้โปรโตคอลสำหรับสิ่งนี้ ใน Kotlin ใช้ interface Facade ยังสะดวกสำหรับการทดสอบการบูรณาการที่ตรวจสอบการจัดระเบียบของส่วนประกอบ

สรุป

  • Facade — แพทเทิร์นเชิงโครงสร้างที่ให้อินเทอร์เฟซที่เรียบง่ายสำหรับระบบย่อยที่ซับซ้อน
  • Service Layer และ UseCase — การนำ Facade ไปใช้ที่พบบ่อยในสถาปัตยกรรมโมบาย
  • Facade ไม่ได้ซ่อนระบบย่อย: ไคลเอนต์สามารถเข้าถึงส่วนประกอบได้โดยตรงเมื่อจำเป็น
  • Facade เทียบกับ Adapter: Facade ทำให้ง่าย Adapter แปลง; Facade เทียบกับ Mediator: Facade ทางเดียว Mediator สองทาง
  • God Facade — แอนตี้แพทเทิร์น: เมธอดมากกว่า 15 เมธอดในคลาสเดียวบ่งบอกถึงการละเมิดหลักการ Single Responsibility
  • โปรโตคอล/อินเทอร์เฟซ สำหรับ Facade จำเป็น — เป็นวิธีเดียวในการทดสอบระบบย่อยด้วย mock
  • คำแนะนำ: นำ Facade มาใช้เมื่อมี 5+ หน้าจอและ 3+ ระบบย่อย; สำหรับโปรเจกต์เล็ก Repository ก็เพียงพอ

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม