首页 > 代码库 > php 常用五种模式
php 常用五种模式
/* 设计模式之单例模式
$_instance 必须声明为静态的私有变量
构造函数必须声明为私有,防止外部程序 new 类从而失去单例模式的意义
getInstance() 方法必须设置为公有的,必须调用此方法以返回实例的一个引用
:: 操作符只能访问静态变量和函数 new 对象会消耗内存
使用场景:最常用的地方是数据库连接
使用单例模式生成一个对象后,该对象可以被其它众多对象所使用
【单例模式适用场景】
1、当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时
2、当这个唯一实例应该是通过子类化可扩展的。并且用户应该无需更改代码就能使用一个扩展的实例时。
*/
class single {
// 在此属性保存实例
private static $_instance;
// 构造函数声明为 private,防止直接创建对象
private function __construct() {
echo ‘this is contructor ‘;
}
// 单例方法
public static function get_instance() {
if(!isset(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
// 阻止用户复制对象实例
private function __clone() {
trigger_error(‘not allow ‘, E_USER_ERROR);
}
public function test() {
echo ‘test method ! ‘;
}
}
$test = single::get_instance();
$test->test();
工厂方法
// 共同接口
interface Sender {
public function send();
}
// 两个实现类
class MailSender implements Sender {
public function send() {
echo "this is mailsender ! ";
}
}
class SmsSender implements Sender {
public function send() {
echo "this is sms sender !";
}
}
// 工厂类接口
interface Provider {
public function produce();
}
// 两个工厂类
class SendMailFactory implements Provider {
public function produce() {
return new MailSender();
}
}
class SendSmsFactory implements Provider {
public function produce() {
return new SmsSender();
}
}
//测试用:
$provider = new SendMailFactory();
$sender = $provider->produce();
$sender->Send();
观察者模式
/* 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新, 又称为发布-订阅(Publish-Subscribe)模式、模型-视图(Model-View)模式、源-监听(Source-Listener)模式、或从属者(Dependents)模式
【观察者模式中主要角色】
抽象主题(Subject)角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以有任意多个观察者。抽象主题提供了增加和删除观察者对象的接口。
抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在观察的主题发生改变时更新自己。
具体主题(ConcreteSubject)角色:存储相关状态到具体观察者对象,当具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
具体观察者(ConcretedObserver)角色:存储一个具体主题对象,存储相关状态,实现抽象观察者角色所要求的更新接口,以使得其自身状态和主题的状态保持一致。
【观察者模式的优点和缺点】
观察者模式的优点:
1、观察者和主题之间的耦合度较小;
2、支持广播通信;
观察者模式的缺点:
1、由于观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。这可能会引起意外的更新。
【观察者模式适用场景】
1、当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。
2、当对一个对象的改变需要同时改变其它对象,而不知道具体有多少个对象待改变。
3、当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换句话说,你不希望这些对象是紧密耦合的。
*/
// 抽象主题角色
interface Subject {
// 增加一个新的观察者对象
public function attach(Observer $observer);
// 删除一个已注册过的观察者对象
public function detach(Observer $observer);
// 通知所有注册过的观察者对象
public function notifyObservers();
}
// 具体主题角色
class ConcreteSubject implements Subject {
private $_observers;
public function __construct() {
$this->_observers = array();
}
public function attach(Observer $observer) {
return array_push($this->_observers, $observer);
}
public function detach(Observer $observer) {
$index = array_search($observer, $this->_observers);
if($index === false || !array_key_exists($index, $this->_observers)) {
return false;
}
unset($this->_observers[$index]);
return true;
}
public function notifyObservers() {
if(!is_array($this->_observers)) {
return false;
}
foreach($this->_observers as $observer) {
$observer->update();
}
return true;
}
}
//抽象观察者角色
interface Observer {
// 更新方法
public function update();
}
class ConcreteObserver implements Observer {
//观察者的名称
private $_name;
public function __construct($name) {
$this->_name = $name;
}
// 更新方法
public function update() {
echo ‘ Observer ‘ . $this->_name . ‘ has notified ‘;
}
}
$subject = new ConcreteSubject();
// 添加第一个观察者
$observer1 = new ConcreteObserver(‘long‘);
$subject->attach($observer1);
echo "111 : <br />";
$subject->notifyObservers();
// 添加第二个观察者
$observer2 = new ConcreteObserver(‘Lin‘);
$subject->attach($observer2);
echo "<br /> 2222 <br />";
$subject->notifyObservers();
//删除第一个观察者
$subject->detach($observer1);
echo "<br /> 333 <br />";
echo $subject->notifyObservers();
命令模式
/* 命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行。这个过程好在,三者相互解耦,任何一方都不用去依赖其他人,只需要做好自己的事儿就行,司令员要的是结果,不会去关注到底士兵是怎么实现的。
Invoker是调用者(司令员),Receiver是被调用者(士兵),MyCommand是命令,实现了Command接口,持有接收对象.命令模式的目的就是达到命令的发出者和执行者之间解耦,实现请求和执行分开
*/
// 接口
interface Command {
public function exe();
}
// 命令
class MyCommand implements Command {
private $receiver;
public function __construct($receiver) {
$this->receive = $receiver;
}
public function exe() {
$this->receive->action();
}
}
// 执行命令者
class Receiver {
public function action() {
echo "Command received ! ";
}
}
// 发出命令
class Invoker {
private $command;
public function __construct($command) {
$this->command = $command;
}
public function action() {
$this->command->exe();
}
}
// 示例
$receiver = new Receiver();
$cmd = new MyCommand($receiver);
$invoker = new Invoker($cmd);
$invoker->action();
策略模式
/* 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。策略模式可以使算法可独立于使用它的客户而变化 策略模式变化的是算法
1、许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法
2、需要使用一个算法的不同变体。
3、算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的,与算法相关的数据结构
4、一个类定义了多种行为,并且 这些行为在这个类的操作中以多个形式出现。将相关的条件分支移和它们各自的Strategy类中以代替这些条件语句
*/
// 策略模式
interface CashSuper {
abstract function acceptCash($m);
}
class CashNormal implements CashSuper {
public function acceptCash($m) {
return ‘this is cashNormal ‘ . $m;
}
}
class CashRebate implements CashSuper {
public function acceptCash($m) {
return ‘this is cashRebate ‘ . $m;
}
}
class CashReturn implements CashSuper {
public function acceptCash($m) {
return ‘this is cashReturn ‘ . $m;
}
}
class CashContext {
public $cs;
public function __construct($cs) {
$this->cs = $cs;
}
public function GetResult($money) {
return $this->cs->acceptCash($money);
}
}
$cc = new CashContext(new CashNormal());
echo $cc -> GetResult(100);