Laravel 是一个非常优雅的Web框架,使用了多种设计模式。php本身是非常自由的脚本语言,但是随着互联网企业的发展,业务越来越复杂,也需要更多的人进行团队协作。作为优秀的开发者,不仅要完成基础的业务开发,为了更好的合作需要遵循面向对象的一系列设计模式。
Laravel的面向对象编程原则
1:使用namespace
防止命名冲突
2:使用autoload
来自动加载函数
使用ArrayAccess
实现配置文件的加载,使一个对象可以通过数组的方式访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| class Config implements \ArrayAccess {
protected $path;
protected $configs = array();
function __construct($path) {
$this->path = $path;
}
function offsetGet($key) {
if (empty($this->configs[$key])) {
$file_path = $this->path.’/’.$key.’.php’;
$config = require $file_path;
$this->configs[$key] = $config;
}
return $this->configs[$Key];
}
function offsetSet($key, $value) {
throw new \Exception(“cannot write config file.”);
}
function offsetExists($key) {
return isset($this->configs[$key];
}
function offsetUnset($key) {
unset($this->configs[$key]);
}
$config = new Config(__dirname__.’/configs’);
$whatkey = $config[‘what_key’];
|
3:psr-4规范
4:链式调用
只要在方法的最后:return $this;
5:魔术方法
- 1)访问不存在的属性,__set()和__get()
- 2)调用不存在的方法 __call()和__callstatic()
- 3)对象作为字符串使用,__toString()
- 4)对象作为方法使用,__invoke()
6:单一职责
一个文件只有一个类,一个类只做好一件事,尽量不要复杂。
7:开放封闭原则
一个类的功能应该是可扩展而不可修改的。
8:依赖倒置
一个类不应该强依赖另一个类,每个类对于另一个类都是可替换的。
9:配置化
尽可能的使用配置而不是硬编码。
10:面向接口编程
只需要关心接口,不需要关心实现。
设计模式的实现
1:工厂模式
例如:Auth::user()
此处Auth这个类就是工厂中的方法,Auth是注册树中的别名。
好处:
类似于函数的封装,使对象有一个统一的生成(实例化)入口。当我们对象所对应的类的类名发生变化的时候,我们只需要改一下工厂类类里面的实例化方法即可。
2:单例模式
好处:
对象不可外部实例化并且只能实例化一次,节省资源。
实现方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| private static $ins = null;
private function __construct() {}
public static function getIns() {
if(self::$ins instanceof self) {
return self::$ins;
} else {
self::$ins = new self();
return self::$ins;
}
}
|
声明一个类的私有或者保护的静态变量,构造方法声明为私有(不允许外部进行new操作),如果不存在则实例化它,然后返回,如果存在则直接返回。
3:注册树模式
使用:
config/app
里的aliases
数组便是一个注册树
好处:
注册树模式就是使用数组结构来存取对象,工厂方法只需要调用一次(可以放到系统环境初始化这样的地方),以后需要调用该对象的时候直接从注册树上面取出来即可,不需要再调用工厂方法和单例模式。
实现方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Register {
protected static $objects
function set($alias,$object) {
self::$objects[$alias]=$object;
}
static function get($name) {
return self::$objects[$name];
}
function _unset($alias) {
unset(self::$onjects[$alias]);
}
}
|
$alias
表示别名,自己设定
在工厂模式中添加
1
| Register::set(‘db1’,$db);
|
其他任何地方调用只需要调用注册器读取即可
1
| Register::$objects[‘db1’];
|
4:适配器模式
将不同工具的不同函数接口封装成统一的API,方便调用。如:mysql
,mysqli
,PDO
。
实现:在接口类里面申明统一的方法体,再让不同的类去实现这个接口,和重写其抽象方法。
1 2 3 4 5 6 7 8 9
| interface Database {
function connect($host,$user,$password,$dbname);
function query($sql);
function close();
}
|
然后再去用不同的工具函数去实现相同的接口。
5:策略模式
好处:
将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,将逻辑判断和具体实现分离,实现了硬编码到解耦,并可实现IOC、依赖倒置、反转控制。
实现:
1.定义一个策略接口文件(UserStrategy.php
),定义策略接口,声明策略
2.定义具体类(FemaleUserStrategy.php
,MaleUserStrategy.php
),实现策略接口,重写策略方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class Page {
protected $strategy;
function index() {
if($request->get(‘female’)) {
$strategy=new FemaleUserStrategy();
} else {
$strategy=new MaleUserStrategy();
}
$this->strategy->method();
}
public function __construct(UserStrategy $strategy) {
$this->strategy=$strategy;
}
}
|
6:数据对象映射模式
好处:将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作,这也是ORM的实现机制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class Model {
public $id;
public $name;
public $email;
……
function __construct($id) {
}
function __destruct() {
}
}
|
7:观察者模式
使用:
1
| Event::fire(new /event);
|
好处:
当一个对象状态发生改变时,依赖它的对象全部会收到通知并自动更新,实现低耦合,非侵入式的通知与更新机制。
(PS:有关abstract
和interface
:http://blog.csdn.net/sunlylorn/article/details/6124319)
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| EventGenerator.php
abstract class EventGenerator{
private $obserers = array();
function addObsever(Observer $observer) {
$this->obserers[] = $observer;
}
function ontify() {
foreach ($this->obserers as $observer){
$observer->handle();
}
}
}
|
event.php
//事件类
1 2 3 4 5 6 7 8 9
| class Event extends EventGenerator{
function trigger(){
$this->ontify();
}
}
|
Observer.php
// 观察者接口
1 2 3 4 5
| interface Observer {
function update($event_info = null);
}
|
Observer1.php
// EventListener
1 2 3 4 5 6 7 8 9
| class Observer1 implements Observer {
function handle($event_info = null){
echo “逻辑1”;
}
}
|
index.php
//Controller中function
1 2 3 4 5
| $event = new \Event();
$event->addObsever(new \Observer1());
$event->trigger();
|
8:原型模式
与工厂模式类似,用于创建对象,不同在于:原型模式是先创建好一个原型对象,再通过clone原型对象来创建新的对象,原型模式适用于大对象的创建,仅需要内存拷贝即可。
1 2 3 4 5 6 7
| $Object = new Object();
$object_1 = clone $Object;
$object_2 = clone $Object;
……
|
9:装饰器模式
若要修改或添加一个类的功能,传统的方式是写一个子类继承它,并重新实现类的方法。装饰器模式仅需在运行时添加一个装饰器对象即可动态的添加或修改类的功能。
传统方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| class Method2 extends Method {
function doSomething() {
echo “<div style=’color:red’>”
parent::doSomething();
echo “</div>”;
}
}
interfa Decorator {
function beforeAction();
function afterAction();
}
class SomeClass {
protected $decorators = [];
function addDecorator(Decorator $decorator) {
$this->decorators[] = $decorator;
}
function beforeMethod() {
foreach ($this->decorators as $row) {
$row->beforeAction();
}
}
function afterMethod() {
decorators = array_reverse($this->decorators);
foreach ($this->decorators as $row) {
$row->afterAction();
}
}
function action() {
$this->beforeMethod();
$this->afterMethod();
}
}
class OneDecorator implements Decorator {
protected $datas;
function __construct($datas = ‘request’) {
$this->datas = $datas;
}
function beforeAction() {
echo “<div style=’color:{$this->datas};’>”;
}
function afterAction() {
echo “</div>”;
}
}
$Object = new \SomeClass();
$Object->addDecorator(new \OneDecorator(‘blue’));
$Object->action();
|
10:迭代器模式
在不需要了解内部实现的前提下,遍历一个聚合对象的内部元素,相对于传统编程方式它可以遍历元素所需的操作。
例如:Object::all()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| Iterator extends Traversable {
abstract public mixed current (void)
abstract public scalar key (void)
abstract public void next (void)
abstract public void rewind (void)
abstract public boolean valid (void)
}
class ObjectAll implements \Iterator {
protected $ids;
protected $index;
protected $data = array();
function __construct() {
}
function current() {
$id = $this->ids[$this->index][‘id’];
return Object::find($id);
}
function next() {
$this->index ++;
}
function valid() {
return $this->index < count($this->$ids);
}
function rewind() {
$this->index = 0;
}
function key() {
return $this->index;
}
}
$objects = new \ObjectAll();
foreach ($objects as $row) {
dump($row->field);
}
|
11:代理模式
在客户端与实体之间建立一个代理对象,客户端对实体进行操作全部委派给代理对象,隐藏实体的具体实现细节(读库与写库分离)。代理对象还可以与业务代码分离,部署到另外的服务器,业务代码中通过PRC来委派任务。
有关mysql的master-slave
:http://www.cnblogs.com/jirglt/p/3549047.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| interface DBproxy {
function getInfo($id);
function setInfo($id, $value);
}
class Proxy implements DBproxy {
function get() {
query
}
function set() {
query
}
}
$proxy = new Proxy();
$proxy->get($id);
$proxy->set($id, $value);
|
12:MVC结构(非设计模式,而是一种工程组织结构)
1:model
——数据和存储的封装
2:view
——展现层的封装
3:controller
——逻辑层(业务代码,功能)的封装