设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的。
设计模式使代码编制真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
可复用面向对象软件系统一般划分为两大类:应用程序工具箱和框架(Framework),我们平时开发的具体软件都是应用程序,PHP的很多封装类属于PHP扩展;而框架是构成一类特定软件可复用设计的一组相互协作的类,ThinkPHP是PHP应用于企业计算的框架。
框架通常定义了应用体系的整体结构类和对象的关系等等设计参数,以便于具体应用实现者能集中精力于应用本身的特定细节。框架主要记录软件应用中共同的设计决策,框架强调设计复用,因此框架设计中必然要使用设计模式。
另外,设计模式有助于对框架结构的理解,成熟的框架通常使用了多种设计模式,如果你熟悉这些设计模式,毫无疑问,你将迅速掌握框架的结构,我们一般开发者如果突然接触YII、TP等框架,会觉得特别难学、难掌握,那么转而先掌握设计模式,无疑是给了你剖析TP或YII系统的一把利器。
设计模式使人们可以更加简单方便地复用成功的设计和体系结构。将已证实的技术表述成设计模式也会使新系统开发者更加容易理解其设计思路。
模式名称(Pattern Name)
一个助记名,它用一两个词来描述模式的问题、解决方案和效果。命名一个新的模式增加了我们的设计词汇。设计模式允许我们在较高的抽象层次上进行设计。基于一个模式词汇表,我们自己以及同事之间就可以讨论模式并在编写文档时使用它们。模式名可以帮助我们思考,便于我们与其他人交流设计思想及设计结果。找到恰当的模式名也是我们设计模式编目工作的难点之一。
laravel框架中的设计模式:https://www.cnblogs.com/agang-php/p/6228795.html
单例模式顾名思义,就是只有一个实例。作为对象的创建模式, 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
某些应用程序资源是独占的,因为有且只有一个此类型的资源。例如,通过数据库句柄到数据库的连接是独占的。您希望在应用程序中共享数据库句柄,因为在保持连接打开或关闭时,它是一种开销,在获取单个页面的过程中更是如此。
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式是一种常见的设计模式,在计算机系统中,线程池、缓存、日志对象、对话框、打印机、数据库操作、显卡的驱动程序常被设计成单例。
单例模式的要点有三个:
一是某个类只能有一个实例;
二是它必须自行创建这个实例;
三是它必须自行向整个系统提供这个实例,必须给其他对象提供这一实例。
为什么要使用单例模式
php的应用主要在于数据库应用,一个应用中会存在大量的数据库操作,在使用面向对象的方式开发时。如果使用单例模式,则可以避免大量的new操作消耗资源,还可以减少数据库连接这样就不容易出现too many connections情况。
如果系统中需要有一个类来全局控制某些配置信息,那么使用单例模式可以很方便的实现,这个可以参看zend Framework的FrontController部分。
在一词页面请求中,便于进行调试,因为所有代码(例如数据库操作类db)都集中在一个类中,我们可以在类中设置钩子,输出日志,从而避免到处是var_dump,echo。
PHP一个主要应用场合就是应用程序与数据库打交道的场景,在一个应用中会存在大量的数据库操作,针对数据库句柄连接数据库的行为,使用单例模式可以避免大量的new操作。因为每次new操作都会消耗系统和内存的资源。
//初始化一个数据库句柄
$db = new DB(...);
//比如有个应用场景是添加一条用户信息
$db->addUserInfo();
//然而我们要在另一地方使用这个用户信息,这时要用到数据库句柄资源,可能会这么做
function test() {
$db = new DB(...);
$db->getUserInfo();
//有些朋友也许会说,可以直接使用global关键字!
global $db;
class User {
//静态变量保存全局实例
private static $_instance = null;
//私有构造函数,防止外界实例化对象
private function __construct() {
}
//私有克隆函数,防止外办克隆对象
private function __clone() {
}
//静态方法,单例统一访问入口
static public function getInstance() {
if (is_null ( self::$_instance ) || ! isset ( self::$_instance )) {
self::$_instance = new self ();
}
return self::$_instance;
}
public function getName() {
echo 'hello world!';
}
}
User::getinstance();
?>
// 下面将得到Example类的单例对象
$test = man::get_instance();
$test = man::get_instance();
$test->test();
/** * 设计模式之单例模式 * $_instance必须声明为静态的私有变量 * 构造函数必须声明为私有,防止外部程序new类从而失去单例模式的意义 * getInstance()方法必须设置为公有的,必须调用此方法以返回实例的一个引用 * ::操作符只能访问静态变量和静态函数 * new对象都会消耗内存 * 使用场景:最常用的地方是数据库连接。 * 使用单例模式生成一个对象后,该对象可以被其它众多对象所使用。 */
http://www.cnblogs.com/yangjinjin/archive/2013/01/31/2887492.html
工厂模式(Factory)允许你在代码执行时实例化对象。它之所以被称为工厂模式是因为它负责“生产”对象。工厂方法的参数是 你要生成的对象对应的类名称。
class Example
{
// The parameterized factory method
public static function factory($type)
{
if (include_once 'Drivers/' . $type . '.php') {
$classname = 'Driver_' . $type;
return new $classname;
} else {
throw new Exception ('Driver not found');
}
}
}
//按上面的方式可以动态加载drivers。如果Example类是一个数据库抽象类,那么 可以这样来生成MySQL和 SQLite驱动对象:
// Load a MySQL Driver
$mysql = Example::factory('MySQL');
// Load a SQLite Driver
$sqlite = Example::factory('SQLite');
//josn 类 html类
注册模式,解决全局共享和交换对象。已经创建好的对象,挂在到某个全局可以使用的数组上,在需要使用的时候,直接从该数组上获取即可。将对象注册到全局的树上。任何地方直接去访问.
class Register{
protected static $objects;
function set($name,$object)
{//将对象注册到全局的树上
self::$objects[$name]=$object;//将对象放到树上
}
static function get($name)
{
return self::$objects[$name];//获取某个注册到树上的对象
}
function _unset($name){
unset(self::$objects[$name]);//移除某个注册到树上的对象。
}
}
将各种截然不同的函数接口封装成统一的API。
PHP中的数据库操作有MySQL,MySQLi,PDO三种,可以用适配器模式统一成一致,使不同的数据库操作,统一成一样的API。类似的场景还有cache适配器,可以将memcache,redis,file,apc等不同的缓存函数,统一成一致。
首先定义一个接口(有几个方法,以及相应的参数)。然后,有几种不同的情况,就写几个类实现该接口。将完成相似功能的函数,统一成一致的方法。
接口 IDatabase
namespace IMooc;
interface IDatabase
{
function connect($host, $user, $passwd, $dbname);
function query($sql);
function close();
}
namespace IMooc\Database;
use IMooc\IDatabase;
class MySQL implements IDatabase
{
protected $conn;
function connect($host, $user, $passwd, $dbname){
$conn = mysql_connect($host, $user, $passwd);
mysql_select_db($dbname, $conn);
$this->conn = $conn;
}
function query($sql)
{
$res = mysql_query($sql, $this->conn);
return $res;
}
function close()
{
mysql_close($this->conn);
}
}
namespace IMooc\Database;
use IMooc\IDatabase;
class MySQLi implements IDatabase
{
protected $conn;
function connect($host, $user, $passwd, $dbname)
{
$conn = mysqli_connect($host, $user, $passwd, $dbname);
$this->conn = $conn;
}
function query($sql)
{
return mysqli_query($this->conn, $sql);
}
function close()
{
mysqli_close($this->conn);
}
}
观察者模式为您提供了避免组件之间紧密耦合的另一种方法。该模式非常简单:一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。
一个简单示例是系统中的用户列表。清单 4 中的代码显示一个用户列表,添加用户时,它将发送出一条消息。添加用户时,通过发送消息的日志观察者可以观察此列表
interface IObserver{
function onChanged( $sender, $args );
}
interface IObservable{
function addObserver( $observer );
}
class UserList implements IObservable{
private $_observers = array();
public function addCustomer( $name ) {
foreach( $this->_observers as $obs )
$obs->onChanged( $this, $name );
}
public function addObserver( $observer ){
$this->_observers []= $observer;
}
}
class UserListLogger1 implements IObserver{
public function onChanged( $sender, $args ) {
echo( "'$args' added to user list\n" );
}
class UserListLogger2 implements IObserver{
public function onChanged( $sender, $args ) {
echo( "'$args' added to user list\n" );
}
class UserListLogger3 implements IObserver{
public function onChanged( $sender, $args ) {
echo( "'$args' added to user list\n" );
}
class UserListLogger4 implements IObserver{
public function onChanged( $sender, $args ) {
echo( "'$args' added to user list\n" );
}
}
$ul = new UserList();
$ul->addObserver( new UserListLogger1() );
$ul->addObserver( new UserListLogger2() );
$ul->addObserver( new UserListLogger3() );
$ul->addObserver( new UserListLogger4() );
$ul->addCustomer( "Jack" );
此代码定义四个元素:两个接口和两个类。IObservable 接口定义可以被观察的对象,UserList 实现该接口,以便将本身注册为可观察。IObserver 列表定义要通过怎样的方法才能成为观察者,UserListLogger 实现 IObserver 接口
测试代码创建 UserList,并将 UserListLogger 观察者添加到其中。然后添加一个消费者,并将这一更改通知 UserListLogger。
认识到 UserList 不知道日志程序将执行什么操作很关键。可能存在一个或多个执行其他操作的侦听程序。例如,您可能有一个向新用户发送消息的观察者,欢迎新用户使用该系统。这种方法的价值在于 UserList 忽略所有依赖它的对象,它主要关注在列表更改时维护用户列表并发送消息这一工作。
此模式不限于内存中的对象。它是在较大的应用程序中使用的数据库驱动的消息查询系统的基础。
有很多程序员往往把框架模式和设计模式混淆,认为MVC是一种设计模式。实际上它们完全是不同的概念。
框架、设计模式这两个概念总容易被混淆,其实它们之间还是有区别的。框架通常是代码重用,而设计模式是设计重用,架构则介于两者之间,部分代码重用,部分设计重用,有时分析也可重用。在软件生产中有三种级别的重用:内部重用,即在同一应用中能公共使用的抽象块;代码重用,即将通用模块组合成库或工具集,以便在多个应用和领域都能使用;应用框架的重用,即为专用领域提供通用的或现成的基础结构,以获得最高级别的重用性。
框架与设计模式虽然相似,但却有着根本的不同。设计模式是对在某种环境中反复出现的问题以及解决该问题的方案的描述,它比框架更抽象;框架可以用代码表示,也能直接执行或复用,而对模式而言只有实例才能用代码表示;设计模式是比框架更小的元素,一个框架中往往含有一个或多个设计模式,框架总是针对某一特定应用领域,但同一模式却可适用于各种应用。可以说,框架是软件,而设计模式是软件的知识。
框架模式有哪些?
MVC、MTV、MVP、CBD、ORM、MVVM等等;
框架有哪些?
C++语言的QT、MFC、gtk,Java语言的SSH 、SSI,php语言的 smarty(MVC模式) TP laravel ,python语言的django(MTV模式)等等
设计模式有哪些?
工厂模式、适配器模式、策略模式等等
详细的设计模式介绍:
https://laravelacademy.org/post/2465.html
https://blog.csdn.net/flitrue/article/details/52614599
简而言之:框架是大智慧,用来对软件设计进行分工;设计模式是小技巧,对具体问题提出解决方案,以提高代码复用率,降低耦合度。
http://baike.baidu.com/view/66964.htm
http://blogread.cn/it/article/6737?f=wb1
http://baike.baidu.com/view/5432454.htm?fr=aladdin
http://www.cnblogs.com/siqi/archive/2012/09/09/2667562.html
http://www.ibm.com/developerworks/cn/opensource/os-php-designptrns/
http://www.ibm.com/developerworks/cn/opensource/os-php-designpatterns/