在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
题外话:前几天到一家公司面试php职位,来面试我的是一位java工程师,囧。随后他随便问了几个php和java共有的名词,要我解释。当时我就渣了。其中一个就是让我描述设计模式都有哪些。虽然我很久之前隐约学习过,奈何时间久远,脑子里早就自动缓存失效。最近整理印象笔记,把这个问题在cnblogs上简单记录一下。 首先,推荐一本书《设计模式》,本人已在网上找到电子版资料,还没开始阅读,欢迎阅读过的小伙伴前来发表阅读感想! 网上很多资料都是从五个设计模式做的介绍,我的笔记同样如此。包括‘工厂模式’、‘单例模式/单元素模式’、‘观察者模式’、'命令链模式'、‘策略模式’ ,下面我们开始一一介绍。 一、工厂模式 概念理解:工厂模式是一种具有创建对象的某种方法的类。我们可以使用工厂类直接创建对象,new的过程由工厂完成。如果我们需要修改所创建的对象类型,只需要更改工厂即可,调用工厂的所有代码都会自动更改。 优点:工厂模式的优点在于创建对象。就是把创建对象的过程封装起来,每次调用工厂的某个方法就自动创建了对象。 设计思想:根据不同参数生成不同类实例。 工厂模式划分:根据抽象程度的不同,可以分为 简单工厂模式、工厂方法模式和抽象工厂模式。下面看一下demo.
*简单工厂模式
<?php /** * 简单工厂模式又叫静态工厂方法模式,理解为可以通过一个静态方法创建对象 * */ interface animal{ function eat(); } class herbivore implements animal{ function eat(){ echo "吃草<br>"; } } class carnivore implements animal{ function eat(){ echo "吃肉<br>"; } } class omnivores implements animal{ function eat(){ echo "杂食<br>"; } } class Demo{ static function createHerbivore(){ return new herbivore; } static function createCarnivore(){ return new carnivore; } static function createOmnivores(){ return new omnivores; } } $herbivore = Demo::createHerbivore(); $herbivore->eat(); $carnivore = Demo::createCarnivore(); $carnivore->eat(); $omnivores = Demo::createOmnivores(); $omnivores->eat();
*工厂方法模式 <?php /** * 工厂模式 定义一个创建对象的接口,让子类决定哪个类实例化,解决简单工厂模式中封闭开发原则 * */ interface animal{ function eat(); } class herbivore implements animal{ function eat(){ echo "吃草<br>"; } } class carnivore implements animal{ function eat(){ echo "吃肉<br>"; } } class omnivores implements animal{ function eat(){ echo "杂食<br>"; } } //将对象的创建抽象成一个接口 interface createAnimal{ function create(); } class FactoryHerbivore implements createAnimal{ function create(){ return new herbivore; } } class FactoryCarnivore implements createAnimal{ function create(){ return new carnivore; } } class FactoryOmnivores implements createAnimal{ function create(){ return new omnivores; } } class Demo{ function test(){ $Factory = new FactoryHerbivore(); $herbivore = $Factory->create(); $herbivore->eat(); $Factory = new FactoryCarnivore(); $carnivore = $Factory->create(); $carnivore->eat(); $Factory = new FactoryOmnivores(); $omnivores = $Factory->create(); $omnivores->eat(); } } $demo = new Demo(); $demo->test(); *抽象工厂方法
<?php /** * 抽象工厂 提供一个创建一系列相关或相互依赖对象的接口 * 与工厂方法的区别,这里定义了一系列接口,工厂方法只有一个 * * */ interface animal{ function eat(); } class yesHerbivore implements animal{ function eat(){ echo "吃草<br>"; } } class noHerbivore implements animal{ function eat(){ echo "不吃草<br>"; } } class yesCarnivore implements animal{ function eat(){ echo "吃肉<br>"; } } class noCarnivore implements animal{ function eat(){ echo "不吃肉<br>"; } } class yesOmnivores implements animal{ function eat(){ echo "杂食<br>"; } } class noOmnivores implements animal{ function eat(){ echo "不杂食<br>"; } } //本质区别在这里,将对象的创建抽象成一个接口 interface createAnimal{ function createYes(); function createNo(); } class FactoryHerbivore implements createAnimal{ function createYes(){ return new yesHerbivore(); } function createNo(){ return new noHerbivore(); } } class FactoryCarnivore implements createAnimal{ function createYes(){ return new yesCarnivore(); } function createNo(){ return new noCarnivore(); } } class FactoryOmnivores implements createAnimal{ function createYes(){ return new yesOmnivores(); } function createNo(){ return new noOmnivores(); } } class Demo{ function test(){ $Factory = new FactoryHerbivore(); $herbivore = $Factory->createYes(); $herbivore->eat(); $herbivore = $Factory->createNo(); $herbivore->eat(); $Factory = new FactoryCarnivore(); $carnivore = $Factory->createYes(); $carnivore->eat(); $carnivore = $Factory->createNo(); $carnivore->eat(); $Factory = new FactoryOmnivores(); $omnivores = $Factory->createYes(); $omnivores->eat(); $omnivores = $Factory->createNo(); $omnivores->eat(); } } $demo = new Demo(); $demo->test();
啊咧,为什么我觉得工厂方法模式和抽象工厂方法模式一样呢。。。
再简单一些理解一下,在Thinkphp框架中的Db.class.php就是工厂类,可以操作mysql,oracle等各数据库,以中间层的姿态,屏蔽掉具体的实现,让程序员不改动原来的查询代码。 总之,工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
推荐阅读:
二、单例/单元素模式
概念理解:单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。我们最常见的应该就是数据库的操作,我们只需要实例化一次,就不需要每次都去new,这样极大的降低了资源的消耗。 其他情况,比如线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序等也都被设计成单例。 单例的特点:只有一个实例,必须自行创建,必须给其他对象提供这一实例。 使用优点:比如在大量数据库操作的场景下,使用单例模式避免频繁大量的new操作,节约了大量的内存和系统的资源。
单例模式的划分:懒汉式单例、饿汉式单例、登记式单例。
<?php class Mysql{ //该属性用来保存实例 private static $conn; //构造函数为private,防止创建对象 private function __construct(){ $this->conn = mysql_connect('localhost','root',''); } //创建一个用来实例化对象的方法 public static function getInstance(){ if(!(self::$conn instanceof self)){ self::$conn = new self; } return self::$conn; } //防止对象被复制 public function __clone(){ trigger_error('Clone is not allowed !'); } } //只能这样取得实例,不能new 和 clone $mysql = Mysql::getInstance();
三、观察者模式
理解:观察者和主题(被观察者)都是用接口。观察者利用主题的接口向主题注册,主题利用观察者的接口通知观察者。观察者和主题之间的关系并非通过继承产生,而是在运行时利用组合的方式产生。
下面我们通过代码来了解观察者模式的具体实现。 //抽象主题 abstract class Subject{ private $observers = array();//观察者队列 public function Attach(Observer $observer) { //观察者对象向主题注册 array_push($this->observers, $observer); } public function Detach(Observer $observer) { //观察者对象从主题注销 遍历查找 foreach ($this->observers as $k=>$v) { if($v==$observer) { unset($this->observers[$k]); } } } function Notify(){ //主题利用观察者的接口通知观察者 以遍历的方式 foreach ($this->observers as $v) { $v->Update(); } } } //抽象观察者 abstract class Observer{ public abstract function Update();//更新操作 } //具体主题 class concreteSubject extends Subject { public $subject_state; } //具体观察者 class ConcreteObserver extends Observer { private $name; private $observerState; public $subject; public function __construct(ConcreteObserver $_sub,$_name) { $this->subject = $_sub; $this->name = $_name; } public function Update() { $this->observerState = $this->subject->subject_state; echo "观察者".$this->name."的新状态是:".$this->observerState."<br/>"; } }
*实现代码* $_s = new concreteSubject();//具体主题对象 $testA = new ConcreteObserver($_s, "小A");//具体观察者对象 $testB = new ConcreteObserver($_s, "小B");//具体观察者对象 $_s->Attach($testA);//将观察者对象通过主题对象注册 $_s->Attach($testB); $_s->subject_state ="状态修改通知"; $_s->Notify();//通知发送
由上我们总结如下:
抽象主题:注册观察者对象,并定义了通知的接口规则 抽象观察者:定义了接到通知后所做的操作接口规则 具体主题:实现抽象主题的接口,接到状态改变则通知观察者 具体观察者:实现具体方法
观察者模式的使用场景: 一个抽象模型有两方面,一方面依赖于另一方面,当对一个对象的改变需要同时改变其他对象,而不需要知道具体有多少对象带改变,松耦合。 缺点:有可能会引起意外的更新。
推荐阅读: PHP设计模式之观察者模式(Observer)详细介绍和代码实例
四、命令链模式
概念:命令链模式以松散耦合主题为基础,发送消息、命令和请求,或通过一组处理程序发送任意内容,每个处理程序都会自行判断自己能否处理请求,如果可以,该请求被处理,进程停止。您可以为系统添加或移除处理程序而不影响其他处理程序。 使用场景:可以使用在用户登录注册时处理不同角色用户的业务逻辑与变量值。
如下代码: interface ICommand { function onCommand($name,$args); } class UserCommand implements ICommand { public function onCommand($name,$args) { if($name !='addUser') return false; echo "UserCommand handling 'addUser' <br>"; return true; } } class MailCommand implements ICommand { public function onCommand($name,$args) { if($name !='mail') return false; echo "UserCommand handling 'mail' <br>"; return true; } } class CommandChain { private $_commands = array(); public function addCommand($cmd){ $this->_commands[] = $cmd; } public function runCommand($name,$args){ foreach ($this->_commands as $cmd){ if($cmd->onCommand($name,$args)) return; } } } $test = new CommandChain(); $test->addCommand(new UserCommand()); $test->addCommand(new MailCommand()); $test->runCommand('addUser', null); $test->runCommand('mail', null);
推荐阅读:
五、策略模式 概念:策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,此模式让算法的变化独立于使用算法的客户,从而让程序更灵活,具有更好的扩展性和维护性。 设计原则: 找出应用中可能需要变化之处,把它们独立出来,不要和不需要的代码混在一起。针对接口编程,不针对实现编程。多用组合,少用继承。
下面看demo
abstract class Person{ abstract function show(); } class minority extends Person { public function show(){ echo "未成年,二折优惠<br>"; } } class adult extends Person { public function show(){ echo "成年,五折优惠<br>"; } } class elder extends Person { public function show(){ echo "老年,免费<br>"; } } class Check { static function getResult($person){ $person = new $person; $person->show(); } } Check::getResult('minority'); Check::getResult('adult'); Check::getResult('elder');
适用场景:
1.多个类之区别在于表现行为不同,可以使用策略模式,在操作时动态选择要执行的策略。 2.需要在不同情况使用不同的策略,或者策略还可能在未来用其他方式实现。 3.对客户隐藏具体策略的实现细节,彼此完全独立。
推荐阅读:
|
2022-07-18
2022-08-30
2022-08-17
2022-11-06
2022-08-17
请发表评论