Natcha Luang - Aroonchai

Trust me I'm Petdo

Bangkok, Thailand

[Blog] รู้จักกับ facade กันหน่อยดีกว่า

จากบทความที่แล้วเราพูดเรื่อง หลักการของ singleton กันไปแล้ว ผมยังรู้สึกว่ามีอีกเรื่องที่อยากจะเขียนถึงคือเรื่องของ facade เป็นอีก design pattern ที่เรามักพบกันบ่อย ๆ ใน framework ที่เขียนด้วย OOP ยุคปัจจุบันนี้ ลองมาดูหลักการและแนวคิดของ facade กันดีกว่าครับ

คำว่า facade เป็นภาษาฝรั่งเศส (façade) อ่านว่า fəˈsäd (ฟะ-ซาด) หมายถึงด้านหน้าของอาคารหรือตึก ที่ได้รับการตกแต่ง ในมุมของวิศกรรมคำนี้หมายถึงการออกแบบด้านหน้าของอาคาร เช่น การวางโครงสร้างของกระจก ขนาดหน้าต่าง​ ฯลฯ

ตัวอย่างการออกแบบหน้าตาตึก

แต่ในเทอมของ software design pattern เราใช้คำนี้ในการออกแบบหน้าตาของไลบรารีหรือคลาส โดยซ่อนสิ่งที่ผู้ใช้งานไม่จำเป็นต้องรู้ไว้ข้างใน ให้ผู้ใช้งานเนี่ยรู้แค่ว่ามันมีหน้าตาของไลบรารีหรือคลาสเราเป็นอย่างไรก็พอแล้ว

ตัวอย่างการออกแบบไลบรารีด้วยหลักการของ facade

<?php

class File {

  protected $adapter;

  public static function open($filename) {
    $this->adapter = new FileAdapter($filename);
    ...
  }

  public static function read($filename, $buffer = 1024) {
    static::open($filename)->read($buffer);
    ...
  }

  public static function write($filename, $contents, $mode = 'a+') {
    static::open($filename)->write($contents, $mode);
    ...
  }

}

จากด้านบนสมมติเรามีไลบรารีสำหรับทำงานกับการเขียนอ่านไฟล์ ซึ่งมีเมดธอดอยู่ด้านในคือ open, read และ write โดยภายในของคลาส File จริง ๆ เป็นการซ่อนการเรียกใช้งานคลาสที่ทำหน้าที่อ่าน/เขียนไฟล์อีกทีหนึ่ง ซึ่งผู้ใช้งานไม่จำเป็นต้องรู้ว่าทำงานอย่างไร รู้แค่ว่าถ้าต้องการเปิดไฟล์ก็แค่ส่งชื่อไฟล์และขนาดของ buffer ที่จะอ่านมาก็พอแล้วเป็นต้น

<?php

File::open('some-file.txt');

$contents = File::read($filename);

File::write('some-file.txt', 'Hello, world!');

ตัวอย่างการเรียกใช้งานไลบรารีที่ออกแบบตามหลักของ facade จะสังเกตว่าผู้ใช้งานไม่ต้องรู้เลยว่าการทำงานภายในเป็นอย่างไร รู้แค่ว่าส่งพารามิเตอร์อะไรไปและจะได้อะไรกลับมาเท่านั้น

ในการทำงานจริงเราจะมักจะออกแบบไลบรารีด้วยหลักการของ facade กันอยู่แล้วเพราะทำให้การใช้งานง่าย แต่ข้อเสียที่สำคัญคือการออกแบบที่ซ่อนทุกอย่างไว้ภายใน ทำให้การเขียนเทสเป็นเรื่องยากมาก ดังนั้นการออกแบบ facade ส่วนมากจะมาพร้อมกับการใช้งาน IoC แทนที่จะเป็นการสร้าง dependency ในคลาสก็ย้ายมาเป็นการส่งผ่านทาง constructor แทน

<?php

class File {

  protected $adapter;

  public function __construct(FileAdapter $adapter) {
    $this->adapter = $adapter;
  }

  ...

}

อ้างอิง

Comments