首页
复制
搜索
前进
后退
重载网页
和我当邻居
给我留言吧
首页
统计
关于
WOW怀旧
友链
更多
留言
壁纸
直播
Search
1
关于《杀死那个石家庄人》背后的故事
3,797 阅读
2
沈阳故宫之旅
608 阅读
3
摄影记录|鸿恩寺
562 阅读
4
赤壁赋| 知不可乎骤得,托遗响于悲风
423 阅读
5
Laravel-admin 删除行|删除回调
366 阅读
编程技术
GoLang
Vue
PHP
Linux
Redis
网络安全
生活杂记
登录
Search
标签搜索
PHP
随笔
Mysql
Laravel-Admin
Laravel
摄影
设计模式
Ab
Linux
Javascript
MAC
支付
CentOs
sh
嘉陵江
南滨路
蓝易云
redis
万能青年
累计撰写
60
篇文章
累计收到
142
条评论
首页
栏目
编程技术
GoLang
Vue
PHP
Linux
Redis
网络安全
生活杂记
页面
统计
关于
WOW怀旧
友链
留言
壁纸
直播
搜索到
1
篇与
的结果
2022-03-06
PHP八大设计模式
单例模式{callout color="#f0ad4e"}$_instance必须声明为静态的私有变量构造函数和析构函数必须声明为私有,防止外部程序new 类从而失去单例模式的意义getInstance()方法必须设置为公有的,必须调用此方法 以返回实例的一个引用::操作符只能访问静态变量和静态函数new对象都会消耗内存使用场景:最常用的地方是数据库连接。使用单例模式生成一个对象后, 该对象可以被其它众多对象所使用。私有的__clone()方法防止克隆对象单例模式,使某个类的对象仅允许创建一个。构造函数private修饰,申明一个static getInstance方法,在该方法里创建该对象的实例。如果该实例已经存在,则不创建。比如只需要创建一个数据库连接。{/callout}{message type="info" content="示例"/}<?php namespace App\Http\Controllers\Admin; use Lcobucci\JWT\Builder; use Lcobucci\JWT\Parser; use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\ValidationData; class JwtAuth { private $token; private $user_id; private $secrect="#awadakvcabzijvjvsuvr"; private $aud="www.test.com"; private $iss="www.test.com"; private $decodeToken; /** * JTW句柄 * @var */ private static $instance; public static function getInstance(){ if (is_null(self::$instance)){ self::$instance =new self(); } return self::$instance; } private function __construct() { } private function __clone(){ } public function getToken(){ return (string)$this->token; } public function setToken($token){ $this->token = $token; return $this; } public function setUid($user_id){ $this->user_id =$user_id; return $this; } public function encode(){ $time= time(); $this->token = (new Builder()) ->setHeader('alg','HS256') ->setIssuer($this->iss) ->setAudience($this->aud) ->setIssuedAt($time) ->setExpiration($time+3600) ->set('user_id',$this->user_id) ->sign(new Sha256(), $this->secrect) ->getToken(); return $this; } /** * @return \Lcobucci\JWT\Token */ public function decode(){ if (!$this->decodeToken){ $this->decodeToken = (new Parser())->parse((string)$this->token); $this->user_id = $this->decodeToken->getClaim('user_id'); } return $this->decodeToken; } /** * @return bool */ public function validate(){ $data = new ValidationData(); $data->setIssuer($this->iss); $data->setAudience($this->aud); return $this->decode()->validate($data); } /** * @return bool */ public function verify(){ $result = $this->decode()->verify(new Sha256() , $this->secrect); return $result; } public function getUid(){ return (new Parser())->parse((string)$this->token)->getClaim('user_id'); } }{message type="info" content="调用"/}$jwtAuth = JwtAuth::getInstance(); $token = $jwtAuth->setUid($id)->encode()->getToken();工厂模式{callout color="#f0ad4e"}工厂模式,工厂方法或者类生成对象,而不是在代码中直接new。 使用工厂模式,可以避免当改变某个类的名字或者方法之后,在调用这个类的所有的代码中都修改它的名字或者参数。{/callout}{message type="info" content="示例"/} // 最基本的工厂模式 class Myname{ public function OutPutMyName(){ return 'hello world~'; } } class NameFactory{ public static function Namefunc(){ return new Myname(); } } $obj=NameFactory::Namefunc(); echo $obj->OutPutMyName(); ?> {message type="warning" content="抽象工厂模式"/}{callout color="#f0ad4e"}抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。{/callout}<?php //定义一个抽象类 abstract class operation { protected $_numA = 0; protected $_numB = 0; protected $_result = 0; public function __construct($a, $b) { $this->_numA = $a; $this->_numB = $b; } //抽象方法所有子类必须实现该方法 protected abstract function getResult(); } //加法运算 class operationAdd extends operation { public function getResult() { $this->_result = $this->_numA + $this->_numB; return $this->_result; } } //减法运算 class operationSub extends operation { public function getResult() { $this->_result = $this->_numA - $this->_numB; return $this->_result; } } //乘法运算 class operationMul extends operation { public function getResult() { $this->_result = $this->_numA * $this->_numB; return $this->_result; } } //除法运算 class operationDiv extends operation { public function getResult() { $this->_result = $this->_numA / $this->_numB; return $this->_result; } } //定义工厂类 class operationFactory { //创建保存示例的静态成员变量 private static $obj; //创建实例的静态方法 public static function CreateOperation($type, $a, $b) { switch ($type) { case '+': self::$obj = new operationAdd($a, $b); break; case '-': self::$obj = new operationSub($a, $b); break; case '*': self::$obj = new operationMul($a, $b); break; case '/': self::$obj = new operationDiv($a, $b); break; } //最后返回这个实例 return self::$obj; } } //最后我们使用工厂模式 $obj = operationFactory::CreateOperation('+', 100, 20); echo $obj->getResult(); 如果还是理解不了这两者的区别,可以看看这个帖子: https://www.zhihu.com/question/20367734注册模式{callout color="#f0ad4e"}单例模式保证了一个类中只有一个实例被全局访问,当你有一组全局对象被全局访问时可能就需要用到注册者模式 (registry),它提供了在程序中有条理的存放并管理对象 (object)一种解决方案。一个“注册模式”应该提供get() 和 set()方法来存储和取得对象(用一些属性key)而且也应该提供一个isValid()方法来确定一个给定的属性是否已经设置。 注册模式通过单一的全局的对象来获取对其它对象的引用{/callout}{message type="info" content="示例"/}class Registry { protected static $store = array(); private static $instance; public static function instance() { if(!isset(self::$instance)) { self::$instance = new self(); } return self::$instance; } public function isValid($key) { return array_key_exists($key,Registry::$store); } public function get($key) { if (array_key_exists($key,Registry::$store)) return Registry::$store[$key]; } public function set($key, $obj) { Registry::$store[$key] = $obj; } } //数据库链接类 class ConnectDB { private $host; private $username; private $password; private $conn; public function __construct($host, $username, $password){ $this->host = $host; $this->username = $username; $this->password = $password; } public function getConnect() { return mysql_connect($this->host,$this->username,$this->password); } } $reg = Registry::instance(); $reg->set('db1', new ConnectDB('localhost', 'root', '123456')); $reg->set('db2', new ConnectDB('127.0.0.2', 'test', 'test')); print_r($reg->get('db1')); print_r($reg->get('db2'));{callout color="#f0ad4e"}注册模式,解决全局共享和交换对象。已经创建好的对象,挂在到某个全局可以使用的数组上,在需要使用的时候,直接从该数组上获取即可。将对象注册到全局的树上。任何地方直接去访问。{/callout}{message type="info" content="示例"/}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::$objects[$alias]); } }适配器模式(interface){callout color="#f0ad4e"}将各种截然不同的函数接口封装成统一的API。 PHP中的数据库操作有MySQL,MySQLi,PDO三种,可以用适配器模式统一成一致,使不同的数据库操作,统一成一样的API。类似的场景还有cache适配器,可以将memcache,redis,file,apc等不同的缓存函数,统一成一致。 首先定义一个接口(有几个方法,以及相应的参数)。然后,有几种不同的情况,就写几个类实现该接口。将完成相似功能的函数,统一成一致的方法。{/callout}{message type="info" content="示例"/}// 接口 IDatabase <?php namespace IMooc; interface IDatabase { function connect($host, $user, $passwd, $dbname); function query($sql); function close(); }MySQL <?php 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); } }PDO <?php namespace IMooc\Database; use IMooc\IDatabase; class PDO implements IDatabase { protected $conn; function connect($host, $user, $passwd, $dbname) { $conn = new \PDO("mysql:host=$host;dbname=$dbname", $user, $passwd); $this->conn = $conn; } function query($sql) { return $this->conn->query($sql); } function close() { unset($this->conn); } }{message type="info" content="示例二"/}/** * 目标角色 */ interface Target { /** * 源类也有的方法1 */ public function sampleMethod1(); /** * 源类没有的方法2 */ public function sampleMethod2(); } /** * 源角色 */ class Adaptee { /** * 源类含有的方法 */ public function sampleMethod1() { echo 'Adaptee sampleMethod1 <br />'; } } /** * 类适配器角色 */ class Adapter extends Adaptee implements Target { /** * 源类中没有sampleMethod2方法,在此补充 */ public function sampleMethod2() { echo 'Adapter sampleMethod2 <br />'; } } class Client { /** * Main program. */ public static function main() { $adapter = new Adapter(); $adapter->sampleMethod1(); $adapter->sampleMethod2(); } }策略模式{callout color="#f0ad4e"}策略模式,将一组特定的行为和算法封装成类,以适应某些特定的上下文环境。 eg:假如有一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有的广告位展示不同的广告。在传统的代码中,都是在系统中加入各种if else的判断,硬编码的方式。如果有一天增加了一种用户,就需要改写代码。使用策略模式,如果新增加一种用户类型,只需要增加一种策略就可以。其他所有的地方只需要使用不同的策略就可以。 首先声明策略的接口文件,约定了策略的包含的行为。然后,定义各个具体的策略实现类。{/callout}{message type="info" content="示例"/}UserStrategy.php <?php /* * 声明策略文件的接口,约定策略包含的行为。 */ interface UserStrategy { function showAd(); function showCategory(); }FemaleUser.php <?php require_once 'Loader.php'; class FemaleUser implements UserStrategy { function showAd(){ echo "2016冬季女装"; } function showCategory(){ echo "女装"; } }MaleUser.php <?php require_once 'Loader.php'; class MaleUser implements UserStrategy { function showAd(){ echo "IPhone6s"; } function showCategory(){ echo "电子产品"; } }Page.php//执行文件 <?php require_once 'Loader.php'; class Page { protected $strategy; function index(){ echo "AD"; $this->strategy->showAd(); echo "<br>"; echo "Category"; $this->strategy->showCategory(); echo "<br>"; } function setStrategy(UserStrategy $strategy){ $this->strategy=$strategy; } } $page = new Page(); if(isset($_GET['male'])){ $strategy = new MaleUser(); }else { $strategy = new FemaleUser(); } $page->setStrategy($strategy); $page->index();php策略模式和适配器模式的区别{callout color="#c5d54d"}PHP中策略模式和适配器模式的区别是:策略模式是通过定义算法,并将算法封装起来,使算法独立于客户而独立变化;适配器模式是使用已经存在的类,将其适配成自己需要的形式。{/callout}观察者模式(Observer){callout color="#f0ad4e"}(Observer),首先要有一个被观察的角色,但ta是【唯一的】。虽然"表演者"只有一个但是"观众"有很多,既一群"人"围观一个"人"。既然有无数个观察者,那么我们需要知道都有哪一些"人"。所以我们需要一个“容器”来记录这些"人",一个类似于数组一样来储存所有观察者的容器。一个"演员"(被观察者),一群"观众"(观察者),一台"摄影机"(记录容器){/callout}1.抽象主题(Subject)角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以有任意多个观察者。 抽象主题提供了增加和删除观察者对象的接口。2.抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在观察的主题发生改变时更新自己。3.具体主题(ConcreteSubject)角色:存储相关状态到具体观察者对象,当具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。4.具体观察者(ConcretedObserver)角色:存储一个具体主题对象,存储相关状态,实现抽象观察者角色所要求的更新接口,以使得其自身状态和主题的状态保持一致主题接口interface Subject{ public function register(Observer $observer); public function notify(); }观察者接口interface Observer{ public function watch(); }{message type="info" content="Subject就是被观察者,Observer就是观众,也就是观察者"/}被观察者class Action implements Subject{ public $_observers=array(); public function register(Observer $observer){ $this->_observers[]=$observer; } public function notify(){ foreach ($this->_observers as $observer) { $observer->watch(); } } }{message type="info" content="Action实现了被观察者接口,他现在就是被观察者,再定义一个$_observers数组,他就是记录观众的容器了。首先实现register方法,用它传入一个观察者,然后塞到数组里,再实现notify()方法,它会遍历容器数组,执行每个观察者的watch()方法。"/}观察者class Cat implements Observer{ public function watch(){ echo "Cat watches TV<hr/>"; } } class Dog implements Observer{ public function watch(){ echo "Dog watches TV<hr/>"; } } class People implements Observer{ public function watch(){ echo "People watches TV<hr/>"; } }{message type="info" content="这里定义了三个观察者,全都实现了Observer接口,前面的Subject会循环调用每个观察者的watch()方法,所以我们需要实现每个观察者的watch()方法。"/}调用$action=new Action(); $action->register(new Cat()); $action->register(new People()); $action->register(new Dog()); $action->notify();{message type="info" content="首先new被观察者对象,执行它的register()方法,把每个观察者都放入容器数组,最后执行notify()方法,通知所有观察者执行自己的方法。"/}原型模式{callout color="#f0ad4e"}为了避免创建对象的成本,使用标准方法 new foo() 创建一个原型并克隆它。{/callout}场景大数据量 ( 例如:通过 ORM 模型一次性往数据库插入 1,000,000 条数据 ) 。 {message type="info" content="示例"/}<?php abstract class BookPrototype { /* * @var string */ protected $title; /* * @var string */ protected $category; abstract public function __clone(); public function getTitle(): string { return $this->title; }// getTitle() end public function setTitle($title) { $this->title = $title; }// setTitle() end }// BookPrototype{} end class BarBookPrototype extends BookPrototype { /* * @var string */ protected $category = 'Bar'; public function __clone() { } }// BarBookPrototype{} end class FooBookPrototype extends BookPrototype { /* * @var string */ protected $category = 'Foo'; public function __clone() { } }// FooBookPrototype{} end $fooPrototype = new FooBookPrototype(); $barPrototype = new BarBookPrototype(); for ($i = 0; $i < 10; $i++) { $book = clone $fooPrototype; $book->setTitle('Foo Book No ' . $i); echo $book->getTitle() . PHP_EOL; } for ($i = 0; $i < 5; $i++) { $book = clone $barPrototype; $book->setTitle('Bar Book No ' . $i); echo $book->getTitle() . PHP_EOL; }结果<?php Foo Book No 0 Foo Book No 1 Foo Book No 2 Foo Book No 3 Foo Book No 4 Foo Book No 5 Foo Book No 6 Foo Book No 7 Foo Book No 8 Foo Book No 9 Bar Book No 0 Bar Book No 1 Bar Book No 2 Bar Book No 3 Bar Book No 4{message type="info" content="PHP 对象复制 : 对象复制可以通过 clone 关键字来完成"/}装饰器模式{callout color="#f0ad4e"}动态地给一个对象添加一些额外的职责,就增加功能来说,Decorator模式相比生成子类更为灵活{/callout}{message type="info" content="例子"/}短信模板接口 <?php interface MessageTemplate { public function message(); }假设有很多模板实现了上面的短信模板接口// 下面这个是其中一个优惠券发送的模板实现 class CouponMessageTemplate implements MessageTemplate { public function message() { return '优惠券信息:我们是全国第一的牛X产品哦,送您十张优惠券!'; } }我们来准备好装饰上面那个过时的短信模板abstract class DecoratorMessageTemplate implements MessageTemplate { public $template; public function __construct($template) { $this->template = $template; } } 过滤新广告法中不允许出现的词汇class AdFilterDecoratorMessage extends DecoratorMessageTemplate { public function message() { return str_replace('全国第一', '全国第二', $this->template->message()); } } 使用我们的大数据部门同事自动生成的新词库来过滤敏感词汇,这块过滤不是强制要过滤的内容,可选择使用class SensitiveFilterDecoratorMessage extends DecoratorMessageTemplate { public $bigDataFilterWords = ['牛X']; public $bigDataReplaceWords = ['好用']; public function message() { return str_replace($this->bigDataFilterWords, $this->bigDataReplaceWords, $this->template->message()); } } 客户端,发送接口,需要使用模板来进行短信发送 class Message { public $msgType = 'old'; public function send(MessageTemplate $mt) { // 发送出去咯 if ($this->msgType == 'old') { echo '面向内网用户发送' . $mt->message() . PHP_EOL; } else if ($this->msgType == 'new') { echo '面向全网用户发送' . $mt->message() . PHP_EOL; } } } $template = new CouponMessageTemplate(); $message = new Message(); // 老系统,用不着过滤,只有内部用户才看得到 $message->send($template); // 新系统,面向全网发布的,需要过滤一下内容哦 $message->msgType = 'new'; $template = new AdFilterDecoratorMessage($template); $template = new SensitiveFilterDecoratorMessage($template); // 过滤完了,发送吧 $message->send($template);引用:https://zhuanlan.zhihu.com/p/102420902 及 https://www.cnblogs.com/yuanwanli/p/8796402.html
2022年03月06日
290 阅读
0 评论
1 点赞