WEB开发者-专业的开发人员学习交流的平台 注册登录
当前位置:首页 > 设计模式>

PHP_设计模式

2017-05-27 13:51:45来源:互联网作者:哥在村口等你

什么是设计模式

在软件开发过程中,经常出现的经典场景的典型解决方案,称为设计模式

如何学习设计模式

典型场景 --> 典型问题 --> 典型解决办法

多态

用来消除逻辑语句.

多态(ploymorphism)是一个生物学上的概念,指同一特种的多种表现形态.

在面向对象中,指某种对象实例的不同表现形态.

<? php

abstract class Tiger {
	public abstract
	function climb();
}

class XTiger extends Tiger {
	public
	function climb() {
		echo 'Drop', '<br/>';
	}
}

class MTiger extends Tiger {
	public
	function climb() {
		echo 'Up', '<br/>';
	}
}

class Cat {
	public
	function climb() {
		echo 'Fly';
	}
}

class Client {
	public static
	function call(Tiger $animal) 
{ // 参数限定不严格,可以更加灵活, 可以传递一个父类类型,就可以有不同的子类形态
		$animal - > climb();
	}
}

Client::call(new XTiger());
Client::call(new MTiger());
Client::call(new Cat());

?>

在23种设计模式中,可以有些模式可以自然消除的.

面向接口开发

减少new 的操作.

熟悉概念:

调用端的概念
客户端(Client)的概念

例如:在Java中,写了一堆类,最终打成一个包。调用端可以把包引入,然后使用类中定义的方法,在开发过程中可以使用查看里面的方法。

假设:开发中引入的是sdk,都不让看。如何调用,必须开放一些接口。存在面向接口开发

接口:共同的规则

面向接口开发

<? php


// 共同接口
// 服务端打包
interface DB {
	function conn();
}


// 服务端开发(不知道将会被谁调用)
class DbMysql implements DB {
	public
	function conn() {
		echo 'conn mysql <br/>';
	}
}

class DbSqlite implements DB {
	public
	function conn() {
		echo 'conn sqlite  <br/>';
	}
}


// ***客户端**** (看不到DbMysql,DbSqlite的内部实现细节)
// 只知道,上述两个类实现了db接口

$db = new DbMysql();
$db - > conn();

$db = new DbSqlite();
$db - > conn();

// 无论是开发者,还是调用者都是为接口负责

简单工厂模式

模式的作用:发生连接的双方,知道的越少越好.

在面向对象设计法则中,重要的开闭原则:对于修改是封闭的,对于扩展是开放的.

<? php


// 共同接口
// 服务端打包
interface DB {
	function conn();
}


// 服务端开发(不知道将会被谁调用)
class DbMysql implements DB {
	public
	function conn() {
		echo 'conn mysql <br/>';
	}
}

class DbSqlite implements DB {
	public
	function conn() {
		echo 'conn sqlite  <br/>';
	}
}


// 简单工厂
class Factory {
	public static
	function createDB($type) {
		if ($type == 'mysql') {
			return new DbMysql();
		} else if ($type == 'sqlite') {
			return new DbSqlite();
		} else {
			throw new Exception('Error db type', 1);
		}
	}
}


// 客户端不知道服务端到底有哪些类名,
// 只知道对方开放了一个Factory::createDB方法.
// 静态方法允许传递数据库名称

$msqyl = Factory::createDB('mysql');
$msqyl - > conn();

$sqlit = Factory::createDB('sqlite');
$sqlit - > conn();


// 如果增加oracle类型,怎么办?
// 服务端要修改Factory的内容(在Java,C++中,改完之后还得再编译)
// 在面向对象设计法则中,重要的开闭原则 --- 对于修改是封闭的,对于扩展是开放的.

// 需求可以扩展子类来实现。

工厂方法

进行扩展,避免对原有数据进行修改,只需要新增代码的子类,就可以完成。

对于修改是封闭的,对于扩展是开放的.

<? php


// 共同接口
// 数据库的接口
interface DB {
	function conn();
}

// 创造数据库的接口
interface Factory {
	function createDB();
}

// 服务端开发(不知道将会被谁调用)
class DbMysql implements DB {
	public
	function conn() {
		echo 'conn mysql <br/>';
	}
}

class DbSqlite implements DB {
	public
	function conn() {
		echo 'conn sqlite  <br/>';
	}
}


class MySqlFactory implements Factory {
	public
	function createDB() {
		return new DbMysql();
	}
}

class SqliteFactory implements Factory {
	public
	function createDB() {
		return new DbSqlite();
	}
}



// ==== 服务器端添加oracle类
// 进行扩展,避免对原有数据进行修改
class orcale implements DB {
	public
	function conn() {
		echo 'conn orcal <br />';
	}
}

class orcaleFactory implements Factory {
	public
	function createDB() {
		return new orcale();
	}
}


// ------客户端开始调用.

$fact = new MysqlFactory();
$db = $fact - > createDB();
$db - > conn();


$fact = new SqliteFactory();
$db = $fact - > createDB();
$db - > conn();

单例模式

常见使用场景:

  1. 需要数据库类的时候

  2. 操作cookie类

  3. 上传图片类

DB.class.phpUpload.class.phpCookie.class.php
// 这三个类都需要读取配置文件信息,而配置文件是共用的,因此配置读取类有一个对象就够了。 
// (如何保证对象只有一个)

PHP对象什么时候全等

二个对象是一个的时候.

单例模式实现

  1. 封闭外部new操作

  2. 内部开公共接口,负责new操作,控制单一实例

  3. 禁止继承覆盖__construcotr

  4. 防止克隆

<? php

/**
  单例模式
*/

// 第一步,普通类

// class Single {

// }


// $s1 = new Single();
// $s2 = new Single();

// var_dump($s1, $s2);
// var_dump($s1 == $s2);

// ---------------------

// 第二步,封锁new操作
// class Single {
//   // 在new 的时候会触发魔术函数,__constructor,可以在 __constructor 魔术函数中做操作 
//   protected function __constructor() { 
// 把__constructor()魔术方法保护起来, 导致的后果,一个对象都没法new。(大门关上了,需要开窗)

//   }
// }

// $s1 = new Single();


// ---------------------

// 第三步,留接口来new对象
// class Single {
//    public static function getIns() { 
// getIns的控制权在class内部,可以在getIns做手脚
//      return new self(); // 返回自身实例
//    } 
//    protected function __constructor() {

//    }
// }

// $s1 = Single::getIns();
// $s2 = Single::getIns();

// var_dump($s1, $s2);
// var_dump($s1 == $s2);



// ---------------------

// 第四步,getIns要预先判断实例
// class Single {
//    protected static $ins = null;
//    public static function getIns() { 
// getIns的控制权在class内部,可以在getIns做手脚
//      if (self::$ins === null) {
//        self::$ins = new self();
//      }
//      return self::$ins;  // 返回自身实例
//    } 
//    protected function __constructor() {

//    }
// }

// $s1 = Single::getIns();
// $s2 = Single::getIns();

// var_dump($s1, $s2);
// var_dump($s1 == $s2); // true

// 问题 :继承之后 constructor 被公开, 可以使用final
// class multi extends Single {
//   public function __constructor() { // 继承之后 constructor 被公开

//   }
// } 




// ---------------------

// 第五步,final,防止继承时,被修改权限
// class Single {
//    protected static $ins = null;
//    public static function getIns() { // getIns的控制权在class内部,可以在getIns做手脚
//      if (self::$ins === null) {
//        self::$ins = new self();
//      }
//      return self::$ins;  // 返回自身实例
//    } 
//    final protected function __constructor() { 
// 方法前加 final,则方法不能被覆盖,类前加final,则类不能被继承。

//    }
// }

// class multi extends Single {
//   public function __constructor() { 
// 继承之后 constructor 被公开

//   }
// } 

// $s1 = Single::getIns();
// $s2 = clone $s1; // 克隆了,又产生了多个对象.

// var_dump($s1, $s2);
// var_dump($s1 === $s2); // true




// ---------------------

// 第六步,禁止clone
class Single {
	protected static $ins = null;
	public static
	function getIns() { // getIns的控制权在class内部,可以在getIns做手脚
		if (self::$ins === null) {
			self::$ins = new self();
		}
		return self::$ins; // 返回自身实例
	}
	final protected
	function __constructor() { 
	// 方法前加 final,则方法不能被覆盖,类前加final,则类不能被继承。

	}

	// 封锁clone
	final protected
	function __clone() {

	}
}

$s1 = Single::getIns();
$s2 = clone $s1; // 克隆了,又产生了多个对象.

var_dump($s1, $s2);
var_dump($s1 === $s2); // true

观察者模式

一个对象变化,引起其它对象的反应。可以让其它几个对象观察变化的对象的反应.

一对多的关系.

优点:解耦。

观察者模式中的三者: SubjectObserverClient;

// Subject
attach() // 记忆多个的对象
detach()  // 告知记忆的对象,变化情况
notify()  // 更新通知

// Observer
update() // 更新对象中执行的逻辑

// Client
// 调用添加观察者`attach()`

JavaScript实现观察者模式:

var select = document.querySelector('select');
var content = document.querySelector('.content');
var ad = document.querySelector('.ad');

// Subject
select.observer = {};
// 添加观察者
select.attach = function(key, obj) {
	this.observer[key] = obj;
}

// 删除观察者
select.detach = function(key) {
	delete this.observer[key];
}

// 更新通知
select.onchange = select.ontify = function() {
	for (var key in this.observer) {
		this.observer[key].update(this);
	}
}

// Observer  
// 观察者
content.update = function(observer) { // 参数是被观察者对象
	alert('content');
	if (observer.value) {
		// 逻辑代码
	}
}

ad.update = function(observer) { // 参数是被观察者对象
	alert('ad');
	if (observer.value) {
		// 逻辑代码
	}
}


// Client
// 监听 
select.attach('content', content);
 // 只需要把独特的表示加入 对象key中
select.attach('ad', ad);

blob.png

PHP实现观察者模式

声明:本站所有模板/文章除标明原创外,均来自网络转载,版权归原作者所有,如果有侵犯到您的权益,请联系本站删除,谢谢合作!
关于我们 - 联系方式 - 版权声明 - 招聘信息 - 邮箱:admin#webkfz.com
Copyright © 2017 webkfz.com Inc. All Rights Reserved. WEB开发者 版权所有