1. 程式人生 > >適配器模式/代理模式/裝飾器模式/工廠模式

適配器模式/代理模式/裝飾器模式/工廠模式

取數 取數據 cat remote struct catch span 擁有 rto

適配器模式

要對原有的類的功能進行擴展,但又不希望改變原有類的功能,來適應新的需求,這時候可以從原有類繼承,實現一個適配器,這不會改變原有類的功能,又可以添加新的功能.

1.類適配器

class A
{
   public function methodA()
   {
	..............
   }
}

class Adapter extends A
{
   private $objectA;
   
   public function methodB()
   {
	echo ‘Append data‘;
   }
}

調用:

$a = new Adapter();
$a->methodA();
$a->methodB();

Adapter既擴展了A類,又沒有改變A類的功能.為了體現裏氏原則,一般繼承類不覆蓋父類的方法(構造方法除外).再者覆蓋了,還不如直接改原來類,適配器也就沒意義了.這個模式看起來特別像是普通的繼承,
只不過是子類實現了父類中不存在的一些方法.

  

2.對象適配器:

class A
{
   public function methodA()
   {
	..............
   }
}

// 適配器
class Adapter
{
   private $objectA;

   public function __construct(A $a)
   {
	$this->$objectA = $a;
   }

   public function methodA()
   {
	$this->objectA->methodA();
   }
   
   public function methodB()
   {
	// ....
   }
}

//調用
$a = new A();
$adapter = new Adapter($a);
$adapter->methodA();
$adapter->methodB();

對象適配器不使用繼承,在構造函數中實例化另一個類.
類適配器和對象適配器的調用方式也有所不同,是否需要構造源類,是兩者的區別.

  

代理模式

代理設計模式構建了透明置於兩個對象之內的一個對象,從而能夠截取或代理這兩個對象間的通信或訪問.

舉個例子,之前我們有個CD類,從127.0.0.1上的mysql數據庫獲取數據;後面因為性能擴展,我們需要該CD類從192.168.2.10上獲取數據.使用代理模式來實現:

class CD
{
    protected $link = null;
    protected static $instance = null;

    protected function __construct()
    {
        $this->connect();
    }

    public static function getInstance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new static(); //此處註意和new self的區別
        }
        return self::$instance;
    }

    public function getAll()
    {
        $res = $this->link->query("SELECT * FROM cd");
        $data = array();

        foreach ($res as $row) {
            $data[] = $row;
        }
        return $data;
    }

    public function connect()
    {
        if (is_null($this->link)) {
            $this->link = new PDO(‘mysql:host=127.0.0.1;dbname=test‘, ‘root‘, ‘root‘);
        }
    }

    public function close()
    {
        $this->link = null;
    }
}

// 代理類
class RemoteCD extends CD
{
    public function connect()
    {
        if (is_null($this->link)) {
            try {
                $this->link = new PDO(‘mysql:host=192.168.2.10;dbname=test‘, ‘root‘, ‘root‘);
            } catch (Exception $e) {
                die($e->getMessage());
            }
        }
    }
}

$cd = RemoteCD::getInstance();
var_dump($cd->getAll());

  

裝飾器模式

代理設計模式構建了透明置於兩個對象之內的一個對象,從而能夠截取或代理這兩個對象間的通信或訪問.

class A
{
   public $nameList = array();

   public function methodA()
   {
	$this->nameList[] = ‘peter‘;
   }
}

// 裝飾器
class Decorator
{
   private $objectA;
   
   public function __construct(A $a)
   {
	$this->objectA = $a;
   }

   public function toUpper()
   {
	// 改變了原有對象的內容
	foreach($this->objectA->nameList as &$val) {
		$val = strtoupper($val);
	}
   }
}

// 調用
$a = new A();
$decorator = new Decorator($a);
$decorator->toUpper();
var_dump($a->nameList);

  

ps:代碼體現了已有對象的部分內容或功能性發生改變,但是不需要改變原始對象的結構.如果不改變已有對象,可以用適配器.裝飾器,必須要裝飾一個對象,裝飾這個意思就是改變已有對象的內容或功能.

工廠模式


提供獲取某個對象的新實例的一個接口,同時使調用代碼避免確定實際實例化基類的步驟.

class A
{
   public function song($songList)
   {
	foreach($songList as $val) {
		echo $val . ‘.mp3‘;
	}
   }
}

class B
{
   public function song($songList)
   {
	foreach($songList as $val) {
		echo $val . ‘.wav‘;
	}
   }
}

class Factory
{
    public static function create($type, $list)
    {
	return new $type($list);
    }
}

$songList = Factory::create(‘A‘, array(‘a.mp3‘, ‘b.mp3‘));

特點:
工廠模式為擁有相同方法的類提供一個統一的訪問實例的接口.
工廠自身並不負責主要數據的處理,全部交由工廠中實例化的類來完成.

  

適配器模式/代理模式/裝飾器模式/工廠模式