/ OOD

[365 วันแห่งโปรแกรม #day56] Facade pattern

วันที่ห้าสิบหกของ ‪#‎365วันแห่งโปรแกรม วันนี้เราจะคุยกันเรื่อง Facade pattern


วันนี้จะเป็นวันสุดท้ายของการคุยกันในเรื่อง Structural Pattern ครับ และผมเลือก Facade pattern เพราะเป็นแพทเทิร์นที่ใช้กันบ่อยมากนั่นเอง

Facade pattern

Facade เป็น object ที่ห่อหุ้มการทำงานที่ซับซ้อนเอาไว้ แล้วแสดง interface ง่ายๆ ให้ client เอาไปใช้

Facade design pattern นั้นถูกใช้บ่อยในระบบขนาดใหญ่ เพราะมีคลาสจำนวนมหาศาล และบางคลาสก็ไม่มี source code อีก แพทเทิร์นนี้จะเข้าไปช่วยซ่อนความซับซ้อนเหล่านั้นเอาไว้

ประโยชน์ของ Facade pattern

  • ทำให้ software library นั้นๆ ง่ายต่อการใช้งาน ง่ายต่อการเข้าใจ ง่ายต่อการทดสอบ
  • ทำให้ software library นั้นอ่านง่าย
  • ลดจำนวน dependencies ของ client ลง เพราะตัว library เองซ่อนความซับซ้อนเหล่านั้นไว้
  • ซ่อน APIs ที่เป็ร poorly designed โดยการครอบด้วย API ใหม่ที่สวยงาม

Diagram

Facade design pattern in UML

จาก diagram จะเห็นว่าคลาสที่เป็น facade นั้นจะมีเมธอด doSomething() ไว้ให้ client นำไปใช้ แต่เจ้า doSomething() เนี่ย ไม่ได้ถูก implement การทำงานในคลาสนี้ทั้งหมด แต่เป็นการเรียกใช้ความสามารถของคลาสอื่นๆ แทน

ดูๆ เหมือนจะคล้ายกลับ Adapter และ Decorator แต่สิ่งที่แพทเทิร์นนี้ต้องการสื่อจริงๆ คือซ่อนการทำงานที่ซับซ้อนเอาไว้ ไม่ใช่แค่ทำให้เข้ากันได้กับ Client หรือเพิ่ม Behavior แบบ Decorator

ตัวอย่างการใช้งาน

วัตถุบนโลกจริงเราส่วนใหญ่ก็เป็น facade ทั้งนั้น เพราะมันปิดการทำงานที่ซับซ้อน แล้วแสดงให้เราเห็นแค่ interface ง่ายๆ เช่น ทีวีก็ประกอบด้วยชิ้นส่วนต่างๆ มากมาย แต่เรารู้แค่ว่าถ้าจะเปิดกดตรงนี้นะ ถ้าจะปรับเสียง เปลี่ยนช่อง ก็กดตรงนู้น อะไรแบบนั้น

ผมขอยกตัวอย่างจากวิกิพีเดียเจ้าเดิมมาเลยละกัน ตัวอย่างนี้คือคลาส facade ของเครื่องคอมพิวเตอร์ครับ

/* Complex parts */

class CPU {
    public void freeze() { ... }
    public void jump(long position) { ... }
    public void execute() { ... }
}

class Memory {
    public void load(long position, byte[] data) { ... }
}

class HardDrive {
    public byte[] read(long lba, int size) { ... }
}

/* Facade */

class ComputerFacade {
    private CPU processor;
    private Memory ram;
    private HardDrive hd;

    public ComputerFacade() {
        this.processor = new CPU();
        this.ram = new Memory();
        this.hd = new HardDrive();
    }

    public void start() {
        processor.freeze();
        ram.load(BOOT_ADDRESS, hd.read(BOOT_SECTOR, SECTOR_SIZE));
        processor.jump(BOOT_ADDRESS);
        processor.execute();
    }
}

/* Client */

class You {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start();
    }
} 

จากตัวอย่างจะเห็นว่าเรา (คลาส You) เวลาจะเปิดใช้เครื่อง computer ก็แค่สั่ง start() ซึ่งจริงๆ แล้วการทำงานมันมีมากกว่านั้น แต่ ComputerFacade ซ่อนเอาไว้ไม่ให้เห็น ตรงนี้แหละครับที่บอกว่า facade ทำให้ client มี dependency ลดลงมาก ใช้งานง่ายขึ้นมาก อ่านโค้ดง่ายขึ้นมาก เพราะ client จะรู้เฉพาะสิ่งที่ควรรู้เท่านั้น (หลักการเดียวกับ abstraction)

Reference

Facade pattern - Wikipedia

#‎day56 #365วันแห่งโปรแกรม ‪#‎โครงการ365วันแห่ง‬...