设计模式六大原则
1、开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
2、里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象。
3、依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
4、单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
5、接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
6、迪米特法则:一个对象应该对其他对象保持最少的了解。
1、Singleton(单例模式)
单例模式是最常见的模式之一,在Web应用的开发中,常常用于允许在运行时为某个特定的类创建仅有一个可访问的实例。
使用场景:只实例化一次,内部实例化,对外只有一个开放方法,只能通过调取该方法进行调取实例化对象。数据库连接。
一个单例类应具备以下特点:
单例类不能直接实例化创建,而是只能由类本身实例化。因此,要获得这样的限制效果,构造函数必须标记为private,从而防止类被实例化。
需要一个私有静态成员变量来保存类实例和公开一个能访问到实例的公开静态方法。
在PHP中,为了防止他人对单例类实例克隆,通常还为其提供一个空的私有__clone()
方法。
单例模式的例子:
<?php /** * Singleton of Database */ class Database { // We need a static private variable to store a Database instance. privatestatic $instance; // Mark as private to prevent it from being instanced. private function__construct() { // Do nothing. } private function__clone() { // Do nothing. } public static function getInstance() { if (!(self::$instance instanceof self)) { self::$instance = new self(); } return self::$instance; } } $a =Database::getInstance(); $b =Database::getInstance(); // true var_dump($a === $b);
2、Factory(工厂模式)
工厂模式是另一种非常常用的模式,正如其名字所示:确实是对象实例的生产工厂。某些意义上,工厂模式提供了通用的方法有助于我们去获取对象,而不需要关心其具体的内在的实现
使用场景:使用方法 new实例化类,每次实例化只需调用工厂类中的方法实例化即可。
优点:由于一个类可能会在很多地方被实例化。当类名或参数发生变化时,工厂模式可简单快捷的在工厂类下的方法中 一次性修改,避免了一个个的去修改实例化的对象。
我们举例子,假设矩形、圆都有同样的一个方法,那么我们用基类提供的API来创建实例时,通过传参数来自动创建对应的类的实例,他们都有获取周长和面积的功能。
<?php interface InterfaceShape { function getArea(); function getCircumference(); } /** * 矩形 */ class Rectangle implements InterfaceShape { private $width; private $height; public function __construct($width, $height) { $this->width = $width; $this->height = $height; } public function getArea() { return $this->width* $this->height; } public function getCircumference() { return 2 * $this->width + 2 * $this->height; } } /** * 圆形 */ class Circle implements InterfaceShape { private $radius; function __construct($radius) { $this->radius = $radius; } public function getArea() { return M_PI * pow($this->radius, 2); } public function getCircumference() { return 2 * M_PI * $this->radius; } } /** * 形状工厂类 */ class FactoryShape { public static function create() { switch (func_num_args()) { case1: return newCircle(func_get_arg(0)); case2: return newRectangle(func_get_arg(0), func_get_arg(1)); default: # code... break; } } } $rect =FactoryShape::create(5, 5); // object(Rectangle)#1 (2) { ["width":"Rectangle":private]=> int(5) ["height":"Rectangle":private]=> int(5) } var_dump($rect); echo "<br>"; // object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) } $circle =FactoryShape::create(4); var_dump($circle);
3、 Prototype(原型模式)
有时候,部分对象需要被初始化多次。而特别是在如果初始化需要耗费大量时间与资源的时候进行预初始化并且存储下这些对象,就会用到原型模式:
使用场景:初始化需要耗费大量资源和时间
4、Adapter(适配器模式)
这种模式允许使用不同的接口重构某个类,可以允许使用不同的调用方式进行调用
使用场景:利用接口,将不同的类 组装一组有相同名称的方法 ,利用接口把 PDO、 mysql、mysqli 封装成相同都数据库操作。
//老的代码 class User { private $name; function __construct($name) { $this->name = $name; } public function getName() { return $this->name; } } //新代码,开放平台标准接口 interface UserInterface { function getUserName(); } class UserInfo implements UserInterface { protected $user; function __construct($user) { $this->user = $user; } public function getUserName() { return $this->user->getName(); } } $olduser = new User('张三'); echo $olduser->getName()."n"; $newuser = new UserInfo($olduser); echo $newuser->getUserName()."n";
5、Bridge(桥接模式)
将抽象部分与它的实现部分分离,使他们都可以独立的变抽象与它的实现分离,即抽象类和它的派生类用来实现自己的对象
桥接与适配器模式的关系(适配器模式上面已讲解):
桥接属于聚合关系,两者关联 但不继承
适配器属于组合关系,适配者需要继承源
6、Decorator(装饰器模式)
根据运行时不同的情景动态地为某个对象调用前后添加不同的行。
使用场景:symfony 控制器中beforepost afterpost 中post提交前和提交后,对数据处理。
当某一功能或方法draw,要满足不同的功能需求时,可以使用装饰器模式;实现方式:在方法的类中建addDecorator(添加装饰器),beforeDraw,afterDraw 3个新方法, 后2个分别放置在要修改的方法draw首尾.然后创建不同的装器类(其中要包含相同的,beforeDraw,afterDraw方法)能过addDecorator添加进去,然后在beforeDraw,afterDraw中循环处理,与观察者模式使用有点相似
1.装饰器模式(Decorator),可以动态地添加修改类的功能
2.一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法
3.使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性
DrawDecorator.php
<?php namespace IMooc; interface DrawDecorator { function beforeDraw(); function afterDraw(); }
Canvas.php
<?php namespace IMooc; class Canvas { public $data; protected $decorators = array(); //Decorator function init($width = 20, $height = 10) { $data = array(); for($i = 0; $i < $height; $i++) { for($j = 0; $j < $width; $j++) { $data[$i][$j] = '*'; } } $this->data = $data; } function addDecorator(DrawDecorator $decorator) { $this->decorators[] = $decorator; } function beforeDraw() { foreach($this->decorators as $decorator) { $decorator->beforeDraw(); } } function afterDraw() { $decorators = array_reverse($this->decorators); foreach($decorators as $decorator) { $decorator->afterDraw(); } } function draw() { $this->beforeDraw(); foreach($this->data as $line) { foreach($line as $char) { echo $char; } echo "<br />\n"; } $this->afterDraw(); } function rect($a1, $a2, $b1, $b2) { foreach($this->data as $k1 => $line) { if ($k1 < $a1 or $k1 > $a2) continue; foreach($line as $k2 => $char) { if ($k2 < $b1 or $k2 > $b2) continue; $this->data[$k1][$k2] = ' '; } } } }
ColorDrawDecorator.php
<?php namespace IMooc; class ColorDrawDecorator implements DrawDecorator { protected $color; function __construct($color = 'red') { $this->color = $color; } function beforeDraw() { echo "<div style='color: {$this->color};'>"; } function afterDraw() { echo "</div>"; } }
index.php
<?php define('BASEDIR', __DIR__); include BASEDIR.'/IMooc/Loader.php'; spl_autoload_register('\\IMooc\\Loader::autoload'); $canvas = new IMooc\Canvas(); $canvas->init(); $canvas->addDecorator(new \IMooc\ColorDrawDecorator('green')); $canvas->rect(3,6,4,12); $canvas->draw();
7、Facade(门面模式)
门面模式 (Facade)又称外观模式,用于为子系统中的一组接口提供一个一致的界面。门面模式定义了一个高层接口,这个接口使得子系统更加容易使用:引入门面角色之后,用户只需要直接与门面角色交互,用户与子系统之间的复杂关系由门面角色来实现,从而降低了系统的耦
8、Strategy(策略模式)
将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,这种模式就是策略模式
使用场景:个人理解,策略模式是依赖注入,控制反转的基础。
例如:一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有广告位展示不同的广告。
MaleUserStrategy.php
<?php namespace IMooc; class MaleUserStrategy implements UserStrategy { function showAd() { echo "IPhone6"; } function showCategory() { echo "电子产品"; } }
FemaleUserStrategy.php
<?php namespace IMooc; class FemaleUserStrategy implements UserStrategy { function showAd() { echo "2014新款女装"; } function showCategory() { echo "女装"; } }
UserStrategy.php
<?php namespace IMooc; interface UserStrategy { function showAd(); function showCategory(); }
<?php interface FlyBehavior{ public function fly(); } class FlyWithWings implements FlyBehavior{ public function fly(){ echo "Fly With Wings \n"; } } class FlyWithNo implements FlyBehavior{ public function fly(){ echo "Fly With No Wings \n"; } } class Duck{ private $_flyBehavior; public function performFly(){ $this->_flyBehavior->fly(); } public function setFlyBehavior(FlyBehavior $behavior){ $this->_flyBehavior = $behavior; } } class RubberDuck extends Duck{ } // Test Case $duck = new RubberDuck(); /* 想让鸭子用翅膀飞行 */ $duck->setFlyBehavior(new FlyWithWings()); $duck->performFly(); /* 想让鸭子不用翅膀飞行 */ $duck->setFlyBehavior(new FlyWithNo()); $duck->performFly();
9、Observer(观察者模式)
一个对象状态发生改变时,依赖它的对象全部会收到通知,并自动更新
使用场景:用户登录,需要写日志,送积分,参与活动 等使用消息队列,把用户和日志,积分,活动之间解耦合。
什么是观察者模式?一个对象通过提供方法允许另一个对象即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。观察者模式是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间紧密耦。看下面例子你就明白了!
<?php /* 观察者接口 */ interface InterfaceObserver { function onListen($sender, $args); function getObserverName(); } // 可被观察者接口 interface InterfaceObservable { function addObserver($observer); function removeObserver($observer_name); } // 观察者抽象类 abstract class Observer implements InterfaceObserver { protected $observer_name; function getObserverName() { return $this->observer_name; } function onListen($sender, $args) { } } // 可被观察类 abstract class Observable implements InterfaceObservable { protected $observers = array(); public function addObserver($observer) { if ($observerinstanceofInterfaceObserver) { $this->observers[] = $observer; } } public function removeObserver($observer_name) { foreach ($this->observersas $index => $observer) { if ($observer->getObserverName() === $observer_name) { array_splice($this->observers, $index, 1); return; } } } } // 模拟一个可以被观察的类 class A extends Observable { public function addListener($listener) { foreach ($this->observersas $observer) { $observer->onListen($this, $listener); } } } // 模拟一个观察者类 class B extends Observer { protected $observer_name = 'B'; public function onListen($sender, $args) { var_dump($sender); echo "<br>"; var_dump($args); echo "<br>"; } } // 模拟另外一个观察者类 class C extends Observer { protected $observer_name = 'C'; public function onListen($sender, $args) { var_dump($sender); echo "<br>"; var_dump($args); echo "<br>"; } } $a = new A(); // 注入观察者 $a->addObserver(new B()); $a->addObserver(new C()); // 可以看到观察到的信息 $a->addListener('D'); // 移除观察者 $a->removeObserver('B'); // 打印的信息: // object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } } // string(1) "D" // object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } } // string(1) "D"
————————————————
原文链接:https://blog.csdn.net/fish_study_csdn/article/details/80911105
评论已关闭。