适配器模式/代理模式/装饰器模式/工厂模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了适配器模式/代理模式/装饰器模式/工厂模式相关的知识,希望对你有一定的参考价值。

适配器模式

要对原有的类的功能进行扩展,但又不希望改变原有类的功能,来适应新的需求,这时候可以从原有类继承,实现一个适配器,这不会改变原有类的功能,又可以添加新的功能.

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‘));

特点:
工厂模式为拥有相同方法的类提供一个统一的访问实例的接口.
工厂自身并不负责主要数据的处理,全部交由工厂中实例化的类来完成.

  

 

以上是关于适配器模式/代理模式/装饰器模式/工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

软件设计模式

Java学习之动态代理

设计模式

23种状态模式的理解

十二种常见设计模式代码详解

设计模式必知必会系列终章