PHP常用设计模式单例, 工厂, 观察者, 责任链, 装饰, 策略,适配,桥接模式
// 多态, 在JAVA中是这样用的, 其实在PHP当中可以自然消除, 因为参数是动态的, 你传什么过来都可以, 不限制类型, 直接调用类的方法 abstract class Tiger { public abstract function climb(); } class XTiger extends Tiger { public function climb() { echo '摔下来'; } } class MTiger extends Tiger { public function climb() { echo '爬到树顶'; } } class Client { public static function call(Tiger $animal) { $animal->climb(); } } Client::call(new XTiger()); Client::call(new MTiger());
// 面向对象里面有一个面向接口开发, 就是一个共同的规格, 你生产插座, 我生产插头 // 共同接口 interface db { function conn(); } // 服务端开发(不知道将会被谁调用) class dbmysql implements db{ public function conn() { echo '连上了MySQL'; } } class dbsqlite implements db{ public function conn() { echo '连上了sqlite'; } } // 客户端, 看不到dbmysql, dbsqlite的内部细节的, 只知道上两个类实现了db接口. $db = new dbmysql(); $db->conn(); // 因为知道这个类实现了db接口, 所以知道有这个conn类 $sqlite = new dbsqlite(); $sqlite->conn(); // 我连我有哪些类我都不希望告诉客户端, 那么怎么进一步进行封装 // 发生连接的双方知道的越少越好, 你还知道我有两个类
// 简单工厂 // 面向对象里面有一个面向接口开发, 就是一个共同的规格, 你生产插座, 我生产插头 // 共同接口 interface db { function conn(); } // 服务端开发(不知道将会被谁调用) class dbmysql implements db{ public function conn() { echo '连上了MySQL'; } } class dbsqlite implements db{ public function conn() { echo '连上了sqlite'; } } // 简单工厂 class Factory { public static function createDB($type) { if($type == 'mysql') { return new dbmysql(); } elseif ($type=='sqlite') { return new dbsqlite(); } else { throw new Exception("Error db type", 1); } } } // 客户端现在不知道对方到底有哪些类名了 // 只知道对方开放了一个Factory::createDB方法 // 方法允许传递数据库名称 $mysql = Factory::createDB('mysql'); $mysql->conn(); $sqlite = Factory::createDB('sqlite'); $sqlite->conn(); // 原本你知道服务器端的两个类名, 觉得你知道的太多, 再封装起来, 只给一个通道, 更好的适应变化 // 如果以后新增oracle类型, 怎么办? // 我们PHP随手改了就行, 像JAVA打包一次很麻烦, 又要修改服务端内容 // 服务端要修改Factory的内容(在java, c++中, 改后还得再编译) // 这个时候就想如何来改进呢 // 在OOD(面向对象设计)的法则中, 有重要的开闭原则--对于修改是封闭的, 对于扩展是开放的. // 你可以新增一个源代码, 不要修改旧的代码 //现在用第二种办法, 叫工厂方法
// 共同接口 interface db { function conn(); } interface Factory { function createDB(); } // 服务端开发(不知道将会被谁调用) class dbmysql implements db{ public function conn() { echo '连上了MySQL'; } } class dbsqlite implements db{ public function conn() { echo '连上了sqlite'; } } class mysqliFactory implements Factory{ public function createDB() { return new dbmysql(); } } class sqliteFactory implements Factory { public function createDB() { return new dbsqlite(); } } // 服务器端添加oracle类 // 前面的代码不用改 // 我就新增一个数据库驱动类和一个工厂, 这样就避免了对源代码的修改 class dboracle implements db { public function conn() { echo '连接上了oracle'; } } class oracleFactory implements Factory { public function createDB() { return new dboracle(); } } // 客户端开始, 对方给了两个api, 一个db的api, 一个是创造数据库的api $fact = new mysqliFactory(); $db = $fact->createDB(); $db->conn(); $fact = new sqliteFactory(); $db = $fact->createDB(); $db->conn();
// 单例 // 一般来说一个中小型网站一个db去连接数据库就行了 // 想想, 能不能只有一个db类, 一个upload类, 一个cookie类 // 类肯定只有一个, 如何保证类的实例也只有一个 // 2个对象是同一个的时候才全等 // 单例模式 class single { protected static $ins = null; // 控制权限, 封锁new操作, 把大门关上了, 需要留一个小窗户 // 方法前加final, 则方法不能被覆盖, 类前加final, 则类不能被继承 final protected function __construct() {} // 防clone final protected function __clone(){} //留一个接口来new对象 public static function getIns() { if(self::$ins == null) { self::$ins = new self(); } return self::$ins; } } $s1 = single::getIns(); $s2 = single::getIns(); if ($s1 === $s2) { echo '是一个对象'; } else { echo '不是一个对象'; }
<title>colour_blue</title> <meta name="description" c> <meta name="keywords" c> <meta http-equiv="content-type" c> <style> div{ margin:10px; width:500px; height:200px; border: 1px solid green; } #content { } #ad { } </style> <script> function t() { var sel = document.getElementsByTagName('select')[0]; // alert(sel.value); if(sel.value == 'male') { document.getElementById('content').style.backgroundColor = 'gray'; document.getElementById('ad').innerHTML = '汽车'; } else if(sel.value=='female') { document.getElementById('content').style.backgroundColor = 'pink'; document.getElementById('ad').innerHTML = '减肥'; } } /** * * 观察上述代码, 如果新增了一个study区, 在切换时, 学习内容也要随之切换, 那么, 就需要改动T函数! 对于修改又开放了. * 思考---如果需要新监听footer区, 如何能不改原来的代码, 而只增加 */ </script> <h1 id="面向过程-不用任务来切换">面向过程, 不用任务来切换</h1> <select name="">// 比如登录, 在登录的时候出于安全考虑要记录上次登录时间 // 出于商业考虑, 给你推荐商品 class user implements SplSubject { public $lognum; public $hobby; protected $observers = null; public function __construct($hobby) { $this->lognum = rand(1, 10); $this->hobby = $hobby; $this->observers = new SplObjectStorage(); } public function login() { // 操作session $this->notify(); } public function attach(SplObserver $observer) { $this->observers->attach($observer); } public function detach(SplObserver $observer) { $this->observers->detach($observer); } public function notify() { $this->observers->rewind(); while($this->observers->valid()) { $observer = $this->observers->current(); $observer->update($this); $this->observers->next(); } } } class secrity implements SplObserver { public function update(SplSubject $subject) { if($subject->lognum lognum.'次安全登录'; } else { echo '这是第'.$subject->lognum.'次登录,异常'; } } } class ad implements SplObserver { public function update(SplSubject $subject) { if($subject->hobby == 'sports') { echo '台湾英锦赛'; } else { echo '好好学习天天向上'; } } } // 实施观察 $user = new user('sports'); $user->attach(new secrity()); $user->attach(new ad()); $user->login();</select>
<title>colour_blue</title> <meta name="description" c> <meta name="keywords" c> <meta http-equiv="content-type" c> <style> div{ margin:10px; width:500px; height:200px; border: 1px solid green; } #content { } #ad { } </style> <h1 id="观察者模式">观察者模式</h1> <select name=""> <option value="male">男式风格</option> <option value="female">女式风格</option> </select> <input type="button" value="观察尾部"> <input type="button" value="别观察尾部了"> <div>我是内容</div> <div>我是广告</div> <div>学习</div> <script> // 服务器端 var sel = document.getElementsByTagName('select')[0]; sel.observers = {}; sel.attach = function(key, obj) { sel.observers[key] = obj; } sel.detach = function(key) { delete this.observers[key]; } sel.onchange = sel.notify = function(){ for(var key in this.observers) { this.observers[key].update(this); } } // 客户端 var content = document.getElementById('content'); content.update = function(observer) { if(observer.value == 'male'){ this.style.backgroundColor = 'gray'; } else if(observer.value=='female'){ this.style.backgroundColor = 'pink'; } } sel.attach('content', content); var ad = document.getElementById('ad'); ad.update = function(observer) { if(observer.value == 'male'){ this.innerHTML = '汽车'; } else if(observer.value=='female'){ this.innerHTML = '减肥'; } } sel.attach('ad', ad); // 客户端和服务端实现了解耦 // 后面有一个学习区, 如果状态改变了, 学习区也要变化 var study = document.getElementById('study'); study.update = function(observer) { if(observer.value == 'male'){ this.innerHTML = '学习计算机'; } else if(observer.value=='female'){ this.innerHTML = '学习美容'; } } sel.attach('study', study); //如果想不观察尾部了 function t1() { sel.atach('study', study); } function t2() { sel.detach('study'); } </script>
.html <title>colour_blue</title> <meta name="description" c> <meta name="keywords" c> <meta http-equiv="content-type" c> <style> div{ margin:10px; width:500px; height:200px; border: 1px solid green; } #content { } #ad { } </style> <h2 id="责任链模式举报过程">责任链模式举报过程</h2>
.html <title>colour_blue</title> <meta name="description" c> <meta name="keywords" c> <meta http-equiv="content-type" c> <style> div{ margin:10px; width:500px; height:200px; border: 1px solid green; } #content { } #ad { } </style> <h2 id="面向过程完成举报过程">面向过程完成举报过程</h2>
.html <title>colour_blue</title> <meta name="description" c> <meta name="keywords" c> <meta http-equiv="content-type" c> <style> div{ margin:10px; width:500px; height:200px; border: 1px solid green; } #content { } #ad { } </style> <h2 id="策略模式-和工厂方法的区别只是在逻辑上的区别-也叫聚合">策略模式 和工厂方法的区别只是在逻辑上的区别, 也叫聚合</h2>
// 装饰器模式 decorator class article { protected $content; public function __construct($content) { $this->content = $content; } public function decorator() { return $this->content; } } $art = new article("好好学习"); echo $art->decorator(); // 文章需要小编加摘要 class BianArticle extends article { public function summary() { return $this->content.'小编加了摘要'; } } $art = new BianArticle('好好学习'); echo $art->summary(); // 又请了SEO人员, 要对文章进行description处理... class SEOArticle extends BianArticle { public function seo() { //... } } // 又有了广告部 class ADArticle extends SEOArticle { // 层次越来越深, 目的却只是给文章加各种内容 }
// 装饰器模式做文章修饰功能 class BaseArt { protected $content; protected $art; public function __construct($content) { $this->content = $content; } public function decorator() { return $this->content; } } //编辑文章摘要 class BianArt extends BaseArt { public function __construct(BaseArt $art) { $this->art = $art; } public function decorator() { return $this->content = $this->art->decorator() . '小编摘要'; } } // SEO class SEOArt Extends BaseArt { public function __construct(BaseArt $art) { $this->art = $art; } public function decorator() { return $this->content = $this->art->decorator() . 'SEO关键词'; } } $b = new SEOArt(new BianArt(new BaseArt('天天向上'))); echo $b->decorator(); $b = new BianArt(new SEOArt(new BaseArt('天天向上'))); echo $b->decorator(); // 装饰的先后顺序可以随便换, 新增多少个装饰者都很方便 // 基类负责创建对象 // 子类负责装饰
// 适配器模式 // 服务器端代码 class weather { public static function show() { $today = [ 'tep' => 28, 'wind' => 7, 'sun' => 'sunny', ]; return serialize($today); } } // 客户端调用 $weather = unserialize(weather::show()); echo '温度: ',$weather['tep'],'<br>'; echo '风力: ',$weather['wind'],'<br>'; echo 'sun: ',$weather['sun'],'<br>'; // 来了一批手机上的java客户端 , 不认识PHP的串化行后的字符串, 怎么办? // 把服务器端代码改了? 旧的客户端会受影响 // 旧的类和函数都不让修改, 如何来进行扩展 // 增加一个适配器 class AdapterWeather extends weather { public static function show() { //拿到旧数据 $today = parent::show(); // 然后开始转换 $today = unserialize($today); $today = json_encode($today); return $today; } } // ==== java, python再来调用就不怕了, 通过适配器调用 $weather = AdapterWeather::show(); $w = json_decode($weather); echo '温度: ',$w->tep,'<br>'; echo '风力: ',$w->wind,'<br>'; echo 'sun: ',$w->sun,'<br>'; // 没有修改旧的方法, 这样就没有影响旧的客户端 // 没有修改旧的类, 说明没有违反开闭原则
// 桥接模式 bridge 尝试 // 论坛给用户发信息, 可以是站内短信, email, 手机 // 本来只需要发站内短信, 后来又需要发email // 一个类只做一件事, 我们把他做成一个接口或者抽象类, 具体的发送由具体的子类实现 interface msg { public function send($to, $content); } class zn implements msg { public function send($to, $content) { echo '站内信给', $to, ' 内容是: ', $content; } } // 有一天要改造, 要发email class email implements msg { public function send($to, $content) { echo 'email给', $to, ' 内容是: ', $content; } } // 后来要发短信 class sms implements msg { public function send($to, $content) { echo '短信给', $to, ' 内容是: ', $content; } } // 后来内容也丰富了, 分普通, 加急, 特急 // 子类就爆炸了, 像数据的三范式一样, 如果完全遵循解耦是不行了 /* class zncommon extends zn; class znwarn extends zn; class zndanger extends zn; class emailcomm extends email; class emailwarn extends email; class emaildanger extends email; .... */ /** * 思考: * 信的发送方式是一个变化因素 * 信的紧急程度是一个变化因素, * 为了不修改父类, 只好考虑2个因素的组织, 不停产生新类.... */
abstract class info { protected $send = null; public function __construct($send) { $this->send = $send; } abstract public function msg($content); public function send($to, $content){ $content = $this->msg($content); $this->send->send($to, $content); } } class zn { public function send($to, $content) { echo '站内给: ', $to, '内容是: ', $content; } } class email { public function send($to, $content) { echo 'email给: ', $to, '内容是: ', $content; } } class sms { public function send($to, $content) { echo 'sms给: ', $to, '内容是: ', $content; } } class commoninfo extends info{ public function msg($content) { return '普通'. $content; } } class warninfo extends info{ public function msg($content) { return '紧急'.$content; } } class dangerinfo extends info{ public function msg($content) { return '紧急'.$content; } } // 用站内发普通信息 $commoninfo = new commoninfo(new zn()); $commoninfo->send('小明', '吃饭了'); //给小刚发紧急手机短信消息 $dangerinfo = new dangerinfo(new sms()); $dangerinfo->send('小刚', '失火了'); // 本来需要3x3个类 // 现在只需要3+3个类了 // 现在耦合了, view中不写逻辑, 数据库三范式, 老有相同的字段, 为了速度, 之前的设计模式都是在解耦, 现在反而增加了耦合, 是为了防止子类爆炸
以上就介绍了PHP常用设计模式单例, 工厂, 观察者, 责任链, 装饰, 策略,适配,桥接模式,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Ramai pengguna akan memilih jenama Huawei apabila memilih jam tangan pintar Antaranya, Huawei GT3pro dan GT4 adalah pilihan yang sangat popular. Apakah perbezaan antara Huawei GT3pro dan GT4? 1. Rupa GT4: 46mm dan 41mm, bahan cermin kaca + badan keluli tahan karat + cangkang belakang gentian resolusi tinggi. GT3pro: 46.6mm dan 42.9mm, bahannya ialah kaca nilam + badan titanium/badan seramik + cangkerang belakang seramik 2. GT4 yang sihat: Menggunakan algoritma Huawei Truseen5.5+ terkini, hasilnya akan lebih tepat. GT3pro: Penambahan elektrokardiogram ECG dan saluran darah serta keselamatan

Fungsi bermaksud fungsi. Ia adalah blok kod yang boleh digunakan semula dengan fungsi tertentu Ia boleh menerima parameter input, melakukan operasi tertentu, dan mengembalikan hasil daripada blok yang boleh digunakan semula. kod untuk meningkatkan kebolehgunaan semula dan kebolehselenggaraan kod.

Mengapa Alat Snipping Tidak Berfungsi pada Windows 11 Memahami punca masalah boleh membantu mencari penyelesaian yang betul. Berikut ialah sebab utama Alat Snipping mungkin tidak berfungsi dengan betul: Focus Assistant dihidupkan: Ini menghalang Snipping Tool daripada dibuka. Aplikasi rosak: Jika alat snipping ranap semasa pelancaran, ia mungkin rosak. Pemacu grafik lapuk: Pemacu yang tidak serasi mungkin mengganggu alat snipping. Gangguan daripada aplikasi lain: Aplikasi lain yang sedang berjalan mungkin bercanggah dengan Alat Snipping. Sijil telah tamat tempoh: Ralat semasa proses naik taraf boleh menyebabkan penyelesaian mudah ini sesuai untuk kebanyakan pengguna dan tidak memerlukan sebarang pengetahuan teknikal khusus. 1. Kemas kini apl Windows dan Microsoft Store

Setiap tahun sebelum Apple mengeluarkan versi utama baharu iOS dan macOS, pengguna boleh memuat turun versi beta beberapa bulan lebih awal untuk mengalaminya terlebih dahulu. Memandangkan perisian ini digunakan oleh orang awam dan pembangun, Apple telah melancarkan versi pembangun dan awam, yang merupakan versi beta awam bagi versi beta pembangun, untuk kedua-duanya. Apakah perbezaan antara versi pembangun dan versi awam iOS? Secara literal, versi pembangun ialah versi ujian pembangun dan versi awam ialah versi ujian awam. Versi pembangun dan versi awam menyasarkan khalayak yang berbeza. Versi pembangun digunakan oleh Apple untuk ujian oleh pembangun Anda memerlukan akaun pembangun Apple untuk memuat turun dan meningkatkannya.

Bahagian 1: Langkah Penyelesaian Masalah Awal Menyemak Status Sistem Apple: Sebelum menyelidiki penyelesaian yang rumit, mari kita mulakan dengan asas. Masalahnya mungkin tidak terletak pada peranti anda; Lawati halaman Status Sistem Apple untuk melihat sama ada AppStore berfungsi dengan betul. Jika terdapat masalah, anda hanya boleh menunggu Apple membetulkannya. Semak sambungan Internet anda: Pastikan anda mempunyai sambungan internet yang stabil kerana isu "Tidak dapat menyambung ke AppStore" kadangkala boleh dikaitkan dengan sambungan yang lemah. Cuba tukar antara Wi-Fi dan data mudah alih atau tetapkan semula tetapan rangkaian (Umum > Tetapkan Semula > Tetapkan Semula Tetapan Rangkaian > Tetapan). Kemas kini versi iOS anda:

php提交表单通过后,弹出的对话框怎样在当前页弹出php提交表单通过后,弹出的对话框怎样在当前页弹出而不是在空白页弹出?想实现这样的效果:而不是空白页弹出:------解决方案--------------------如果你的验证用PHP在后端,那么就用Ajax;仅供参考:HTML code

Dalam artikel ini, kita akan belajar tentang fungsi enumerate() dan tujuan fungsi "enumerate()" dalam Python. Apakah fungsi enumerate()? Fungsi enumerate() Python menerima pengumpulan data sebagai parameter dan mengembalikan objek penghitungan. Objek penghitungan dikembalikan sebagai pasangan nilai kunci. Kuncinya ialah indeks yang sepadan dengan setiap item, dan nilainya ialah item. Syntax enumerate(iterable,start) Parameters iterable - Yang diluluskan dalam pengumpulan data boleh dikembalikan sebagai objek enumeration, dipanggil iterablestart - Seperti namanya, indeks permulaan objek enumeration ditakrifkan oleh permulaan. kalau kita abaikan

Penjelasan terperinci tentang peranan dan fungsi jadual MySQL.proc ialah sistem pengurusan pangkalan data relasi yang popular Apabila pembangun menggunakan MySQL, mereka sering melibatkan penciptaan dan pengurusan prosedur tersimpan (StoredProcedure). Jadual MySQL.proc ialah jadual sistem yang sangat penting Ia menyimpan maklumat yang berkaitan dengan semua prosedur tersimpan dalam pangkalan data, termasuk nama, definisi, parameter, dsb. prosedur tersimpan. Dalam artikel ini, kami akan menerangkan secara terperinci peranan dan kefungsian jadual MySQL.proc
