PHP 工厂模式 实例讲解
单例模式又称为职责模式,它用来在程序中创建一个单一功能的访问点,通俗地说就是实例化出来的对象是唯一的。
所有的单例模式至少拥有以下三种公共元素:
1. 它们必须拥有一个构造函数,并且必须被标记为private
2. 它们拥有一个保存类的实例的静态成员变量
3. 它们拥有一个访问这个实例的公共的静态方法
单例类不能再其它类中直接实例化,只能被其自身实例化。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。
单例模式的优缺点:
主要优点:
1、提供了对唯一实例的受控访问。
2、由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。
3、允许可变数目的实例。
主要缺点:
1、由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
2、单例类的职责过重,在一定程度上违背了“单一职责原则”。
3、滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。
例子:
1 class Single {
2 private $name;//声明一个私有的实例变量
3 private function __construct(){//声明私有构造方法为了防止外部代码使用new来创建对象。
4
5 }
6
7 static public $instance;//声明一个静态变量(保存在类中唯一的一个实例)
8 static public function getinstance(){//声明一个getinstance()静态方法,用于检测是否有实例对象
9 if(!self::$instance) self::$instance = new self();
10 return self::$instance;
11 }
12
13 public function setname($n){ $this->name = $n; }
14 public function getname(){ return $this->name; }
15 }
16
17
18 $oa = Single::getinstance();
19 $ob = Single::getinstance();
20 $oa->setname('hello world');
21 $ob->setname('good morning');
22 echo $oa->getname();//good morning
23 echo $ob->getname();//good morning
再来一个例子:
class Test{
private static $_instance;//保存类的静态成员变量
//定义一个私有的构造函数,确保单例类不能通过new关键字实例化,只能被其自身实例化
private final function __construct()
{
echo 'test_consttuct';
}
//定义克隆方法,确保单例类只能被克隆或者复制
private function __clone()
{
// TODO: Implement __clone() method. }
//公共的静态方法
public static function getInstance()
{
//检测类是否被实例化
if(!(self::$_instance instanceof self))
{
self::$_instance = new test();
}
return self::$_instance;
}
}
test::getInstance();
简单工厂模式:
①抽象基类:类中定义抽象一些方法,用以在子类中实现
②继承自抽象基类的子类:实现基类中的抽象方法
③工厂类:用以实例化对象
看完文章再回头来看下这张图,效果会比较好
1 采用封装方式
2
3 <?php
4 class Calc{
5 /**
6 * 计算结果
7 *
8 * @param int|float $num1
9 * @param int|float $num2
10 * @param string $operator
11 * @return int|float
12 */
13 public function calculate($num1,$num2,$operator){
14 try {
15 $result=0;
16 switch ($operator){
17 case '+':
18 $result= $num1+$num2;
19 break;
20 case '-':
21 $result= $num1-$num2;
22 break;
23 case '*':
24 $result= $num1*$num2;
25 break;
26 case '/':
27 if ($num2==0) {
28 throw new Exception("除数不能为0");
29 }
30 $result= $num1/$num2;
31 break;
32 }
33 return $result;
34 }catch (Exception $e){
35 echo "您输入有误:".$e->getMessage();
36 }
37 }
38 }
39 $test=new Calc();
40 // echo $test->calculate(2,3,'+');//打印:5
41 echo $test->calculate(5,0,'/');//打印:您输入有误:除数不能为0
42 ?>
优点:以上代码使用了面向对象的封装特性,只要有了include这个类,其他页面就可以随便使用了
缺点:无法灵活的扩展和维护
比如:想要增加一个“求余”运算,需要在switch语句块中添加一个分支语句,代码需要做如下改动
1 添加分支语句
2
3 <?php
4 class Calc{
5 public function calculate($num1,$num2,$operator){
6 try {
7 $result=0;
8 switch ($operator){
9 //......省略......
10 case '%':
11 $result= $num1%$num2;
12 break;
13 //......省略......
14 }
15 }catch (Exception $e){
16 echo "您输入有误:".$e->getMessage();
17 }
18 }
19 }
20 ?>
代码分析:用以上方法实现给计算器添加新的功能运算有以下几个缺点
①需要改动原有的代码块,可能会在为了“添加新功能”而改动原有代码的时候,不小心将原有的代码改错了
②如果要添加的功能很多,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’,或者添加一些程序员专用的计算功能,比如:And, Or, Not, Xor,这样就需要在switch语句中添加N个分支语句。想象下,一个计算功能的函数如果有二三十个case分支语句,代码将超过一屏,不仅令代码的可读性大大降低,关键是,为了添加小功能,还得让其余不相关都参与解释,这令程序的执行效率大大降低
解决途径:采用OOP的继承和多态思想
1 简单工厂模式的初步实现
2 <?php
3 /**
4 * 操作类
5 * 因为包含有抽象方法,所以类必须声明为抽象类
6 */
7 abstract class Operation{
8 //抽象方法不能包含函数体
9 abstract public function getValue($num1,$num2);//强烈要求子类必须实现该功能函数
10 }
11 /**
12 * 加法类
13 */
14 class OperationAdd extends Operation {
15 public function getValue($num1,$num2){
16 return $num1+$num2;
17 }
18 }
19 /**
20 * 减法类
21 */
22 class OperationSub extends Operation {
23 public function getValue($num1,$num2){
24 return $num1-$num2;
25 }
26 }
27 /**
28 * 乘法类
29 */
30 class OperationMul extends Operation {
31 public function getValue($num1,$num2){
32 return $num1*$num2;
33 }
34 }
35 /**
36 * 除法类
37 */
38 class OperationDiv extends Operation {
39 public function getValue($num1,$num2){
40 try {
41 if ($num2==0){
42 throw new Exception("除数不能为0");
43 }else {
44 return $num1/$num2;
45 }
46 }catch (Exception $e){
47 echo "错误信息:".$e->getMessage();
48 }
49 }
50 }
51 ?>
这里采用了面向对象的继承特性,首先声明一个虚拟基类,在基类中指定子类务必实现的方法(getValue())
分析:通过采用面向对象的继承特性,我们可以很容易就能对原有程序进行扩展,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’等等。
<?php
/**
* 求余类(remainder)
*
*/
class OperationRem extends Operation {
public function getValue($num1,$num2){
return $num1%$num12;
}
}
?>
我们只需要另外写一个类(该类继承虚拟基类),在类中完成相应的功能(比如:求乘方的运算),而且大大的降低了耦合度,方便日后的维护及扩展
现在还有一个问题未解决,就是如何让程序根据用户输入的操作符实例化相应的对象呢?
解决办法:使用一个单独的类来实现实例化的过程,这个类就是工厂
代码如下:
1 <?php
2 /**
3 * 工程类,主要用来创建对象
4 * 功能:根据输入的运算符号,工厂就能实例化出合适的对象
5 *
6 */
7 class Factory{
8 public static function createObj($operate){
9 switch ($operate){
10 case '+':
11 return new OperationAdd();
12 break;
13 case '-':
14 return new OperationSub();
15 break;
16 case '*':
17 return new OperationSub();
18 break;
19 case '/':
20 return new OperationDiv();
21 break;
22 }
23 }
24 }
25 $test=Factory::createObj('/');
26 $result=$test->getValue(23,0);
27 echo $result;
28 ?>
总结
区别
简单工厂模式(静态方法工厂模式) : 用来生产同一等级结构中的任意产品。(不能增加新的产品)
工厂模式 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂 :用来生产不同产品种类的全部产品。(不能增加新的产品,支持增加产品种类)
适用范围
简单工厂模式:
工厂类负责创建的对象较少,操作时只需知道传入工厂类的参数即可,对于如何创建对象过程不用关心。
工厂方法模式:
满足以下条件时,可以考虑使用工厂模式方法
当一个类不知道它所必须创建对象的类时
一个类希望由子类来指定它所创建的对象时
当类将创建对象的职责委托给多个帮助子类中得某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时
抽象工厂模式:
满足以下条件时,可以考虑使用抽象工厂模式
系统不依赖于产品类实例如何被创建,组合和表达的细节。
系统的产品有多于一个的产品族,而系统只消费其中某一族的产品
同属于同一个产品族是在一起使用的。这一约束必须在系统的设计中体现出来。
系统提供一个产品类的库,所有产品以同样的接口出现,从而使客户端不依赖于实现。
以上几种,归根结底,都是将重复的东西提取出来,以方便整体解耦和复用,修改时方便。可根据具体需求而选择使用。
如果帮到了您,可以支持一下,谢谢您的支持!
PHP 工厂模式 实例讲解的更多相关文章
- PHP设计模式之 单例模式 工厂模式 实例讲解
单例模式又称为职责模式,它用来在程序中创建一个单一功能的访问点,通俗地说就是实例化出来的对象是唯一的.所有的单例模式至少拥有以下三种公共元素:1. 它们必须拥有一个构造函数,并且必须被标记为priva ...
- PHP中“简单工厂模式”实例讲解
原创文章,转载请注明出处:http://www.cnblogs.com/hongfei/archive/2012/07/07/2580776.html 简单工厂模式:①抽象基类:类中定义抽象一些方法, ...
- PHP中“简单工厂模式”实例讲解(转)
? 1 2 3 4 5 6 7 8 原创文章,转载请注明出处:http://www.cnblogs.com/hongfei/archive/2012/07/07/2580776.html 简单 ...
- .Net简单工厂模式,工厂模式,抽象工厂模式实例
1.定义 简单工厂模式:是由一个工厂对象决定创建出哪一种产品类的实例.简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现. 工厂模式:定义一个用于创建对象的接口, ...
- JavaScript设计模式-10.工厂模式实例xhr
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Python设计模式之"外观模式"实例讲解
Python中设计模式之外观模式主张以分多模块进行代码管理而减少耦合,下面用实例来进行说明. 应用特性: 在很多复杂而小功能需要调用需求时,而且这些调用往往还有一定相关性,即一调用就是一系列的. 结构 ...
- PHP 单列模式实例讲解以及参考网址
1,http://blog.csdn.net/jungsagacity/article/details/7618587 2,http://www.cnblogs.com/lh460795/archiv ...
- java代理模式实例讲解
下面这个是设计模式课上的例子: import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import ...
- PHP设计——单例模式与工厂模式
一.单例模式又称为职责模式,它用来在程序中创建一个单一功能的访问点,通俗地说就是实例化出来的对象是唯一的.所有的单例模式至少拥有以下三种公共元素:1. 它们必须拥有一个构造函数,并且必须被标记为pri ...
随机推荐
- 3.Java日志框架slf4j、jcl、jul、log4j1、log4j2、logback大总结
一.slf4j.jcl.jul.log4j1.log4j2.logback JUL:JDK中的日志记录工具,也常称为JDKLog.jdk-logging. LOG4J1:一个具体的日志实现框架. LO ...
- jdk源码剖析:Synchronized
开启正文之前,先说一下源码剖析这一系列,就以"死磕到底"的精神贯彻始终,最少追踪到JVM指令(再往下C语言实现了). =========正文分割线=========== Sync ...
- 转接口IC NCS8807:LVDS转MINI LVDS芯片
LVDS 4K TCON w/ Scaler1 General Description NCS8807 is an LVDS 4K TCON with advanced scaling func ...
- AngularJS1.X学习笔记14-动画(解读文档)
最近在看算法分析,那个大O啊,小o啊,分治法啊(目前就看到这里),真是搞死了.这回呢休息一下,学学AngularJS动画,上一篇文章根据自由男人的书简单谈到了动画的话题,发现反响很大(好吧,我说慌了, ...
- linux mail命令详解
用程序发送邮件有3种方式,分别是: 1.模拟http请求邮件服务商网页实现邮件的发送 2.如果邮件服务商开通了smtp服务,那么可以通过smtp协议通过邮件代理服务商发送邮件 3.自己部署邮件服务器, ...
- Java事物基础总结
1.什么是事物? 事物是逻辑上的的一种操作,这个操作过程中的每一个元素要么全部成功,要么全部失败.例如,银行转账过程视为一个事物,转出过程和转入过程要求全部成功或全部失败,通过提交事物或者回滚事物实现 ...
- STAR法则的感想
STAR法则百度百科上被解释为,面试官用于收集面试者信息的工具,而我个人理解,它更像是一个表达技巧,叙述结构,我们先来看看什么是STAR法则: STAR法则,即为Situation Task Acti ...
- Apriori算法介绍(Python实现)
导读: 随着大数据概念的火热,啤酒与尿布的故事广为人知.我们如何发现买啤酒的人往往也会买尿布这一规律?数据挖掘中的用于挖掘频繁项集和关联规则的Apriori算法可以告诉我们.本文首先对Apriori算 ...
- yii2 advance安装
转载自:http://www.genshuixue.com/i-cxy/p/7986531 1. 前提条件,php版本得> 5.4D:\phpStudy>php -v PHP 5.5.17 ...
- SysTick定时器
SysTick是一个24位的倒计数定时器,当计到0时,将从RELOAD寄存器中自动重装载定时初值.只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息.下边小结了SysTick的相关寄 ...