oop的三种设计模式(单例、⼯⼚、策略)
单例模式:
废话不多说,我们直接上代码:
<?php
/**
三私⼀公
*私有的静态属性:保存类的单例
*私有的__construct():阻⽌在类的外部实例化
*私有的__clone():阻⽌在类的外部clone对象
*共有的静态⽅法:获取类的单例
*/
class DanLi{
private static $instance;  //保存类的单例
private function __construct() {    //阻⽌在类的外部实例化
}
private function __clone() {    //阻⽌在类的外部clone对象
}
//获取当前类的单例
public static function getInstance() {
if(!self::$instance instanceof self)//$instance中保存的不是MySQLDB类的单例就实例化
self::$instance=new self();
return self::$instance; //返回单例
}
}
//测试
$db1=DanLi::getInstance();
$db2=DanLi::getInstance();
var_dump($db1,$db2);
我们可以看到结果为下图:
我们可以看到,结果为:两个实例化出来对象是⼀样的。这就体现了我们单例的精髓(只能实例化出来⼀个实例,并且不可复制,能够节省系统资源)
注意:静态变量上存在内存中的,它不会因为程序执⾏完毕⼆消失,所以我们第⼆次实例化的时候,会检测到instance的存在,因⽽直接返回已经存在的instance实例。
下⾯我们来看⼀下单例的实际运⽤:⽤于数据库连接类,因为是数据库连接,我们没有必要每⼀次操作数据库都进⾏⼀次数据库类的实例化,那样会⼤⼤的消耗系统资源。所以,我们⽤到了单例模式,代码如下://初始化连接参数
private function initParam($config){
$this->host=isset($config['host'])?$config['host']:'';
$this->port=isset($config['port'])?$config['port']:'3306';
$this->user=isset($config['user'])?$config['user']:'';
$this->pwd=isset($config['pwd'])?$config['pwd']:'';
$this->charset=isset($config['charset'])?$config['charset']:'utf8';
$this->dbname=isset($config['dbname'])?$config['dbname']:'';
}
private function connect(){
$this->link=@mysql_connect("{$this->host}:{$this->port}",$this->user,$this->pwd) or die('数据库连接失败');
}
private function setCharset(){
$sql = "set names '{$this->charset}'";
$this->query($sql);
}
private function selectDB(){
$sql = "use `{$this->dbname}`";
$this->query($sql);
}
private function __construct($config){
$this->initParam($config);
$this->connect();
$this->setCharset();
$this->selectDB();
}
private function __clone(){
}
public static function getInstance($config=array()) {
if(!self::$instance instanceof self)
self::$instance=new self($config);
return self::$instance;
}
public function query($sql){
if(!$result=mysql_query($sql,$this->link)){
echo 'sql语句执⾏失败<br />';
exit;
}
return $result;
}
}
$config=array(
'host' => '127.0.0.1',
'user' => 'root',
'dbname' => 'accounts'
$db = Test::getInstance($config);
$sql = "select * from acc_wechat";
$info = $db->query($sql);
while($rows = mysql_fetch_row($info)){
//echo $rows[1].'<br>';
//var_dump($rows);
echo $rows[0].'-'.$rows[1].'<br />';
}
var_dump($info);
>
通过以下代码,我们就⼤体了解了:单例的原理及实际运⽤。
⼯⼚模式:
⼯⼚模式可以这样来概括:⼯⼚⾥⾯已经把你所需要的东西都准备好了,要什么⾃⼰拿就⾏。集体实现代码如下:
<?php
//要实现的接⼝
interface BaseClass{
  public function say();
}
单例模式的几种实现方式
//实现接⼝类1
class Man implements BaseClass{
  function say(){
    return 'I'm Man.';
  }
}
//实现接⼝类2
class Women implements BaseClass{
  function say(){
    return 'I'm Women.';
  }
}
//构建⼯⼚类
class Factory{
  public static function man(){
    return new Man();
  }
  public static function  Women(){
    return new Women();
  }
}
//获取⼯⼚中Man这个类
$man=Factory::man();
//调⽤Man类中的say⽅法
$man->say();
//获取⼯⼚中Women这个类
$women=Factory::women();
//调⽤Women类中的say⽅法
$women->say();
>
以上就是⼯⼚模式的实现过程。
策略模式:
这个我也不知道该怎么形容,直接上代码吧。
<?php
//接⼝类(抽象策略⾓⾊)
interface BaseClass{
  public function name();
}
//实现接⼝类1(环境⾓⾊1(对抽象策略⾓⾊的引⽤))
class XiaoMing implements BaseClass{
  function name(){
    return 'My name is XiaoMing.';
  }
}
/
/实现接⼝类2(环境⾓⾊2(对抽象策略⾓⾊的引⽤))
class XiaoHong implements BaseClass{
  function name(){
    reutrn 'My name is XiaoHong.';
  }
}
//构建具体策略⾓⾊
class CeLve{
  public function call($object){
    return $object->name();
  }
}
//实例化策略类
$obj = new CeLve();
//传⼊⼩明类并调⽤name⽅法,打印出结果
echo $obj->call(new XiaoMing());
//传⼊⼩红类并调⽤name⽅法,打印出结果
echo $obj->call(new XiaoHong());
>
关于⼯⼚模式和策略模式,有以下总结。
该总结出⾃:
⼯⼚(Factory)模式我们可以做如下理解,假设有⼀个Audi的公司⽣产汽车(似乎也不⽤假设了),它
掌握⼀项核⼼的技术就是⽣产汽车,另⼀⽅⾯,它⽣产的汽车是有不同型号的,并且在不同的⽣产线上进⾏组装。当客户通过销售部门进⾏预定后,Audi公司将在指定的⽣产线上为客户⽣产出它所需要的汽车。
策略(Strategy)模式在结构上与⼯⼚模式类似,唯⼀的区别是⼯⼚模式实例化⼀个产品的操作是在服务端来做的,换句话说客户端传达给服务端的只是某种标识,服务端根据该标识实例化⼀个对象。⽽策略模式的客户端传达给服务端的是⼀个实例,服务端只是将该实例拿过去在服务端的环境⾥执⾏该实例的⽅法。这就好⽐⼀个对汽车不甚了解的⼈去买车,他在那⼀⽐划,说要什么什么样的,销售部门根据他的这个“⽐划”来形成⼀份订单,这就是⼯⼚模式下的⼯作⽅式。⽽策略模式下那个顾客就是个⾏家,他⾃⼰给出了订单的详细信息,销售部门只是转了⼀下⼿就交给⽣产部门去做了。通过两相对⽐,我们不难发现,采⽤⼯⼚模式必须提供⾜够灵活的销售部门,如果⽤户有了新的需求,销售部门必须马上意识到这样才可以做出合适的订单。所以倘⼀款新车出来了,⽣产部门和销售部门都需要更新,对顾客来说也需要更新对新车的描述所以需要改动的地⽅有三处。⽽策略模式中的销售部门⼯作⽐较固定,它只负责接受订单并执⾏特定的⼏个操作。当⼀款新车出来时,只需要对服务端的⽣产部门和客户端的代码进⾏更新,⽽不需要更新销售部门的代码。
技术⽀持:
简单⼯⼚和策略的基础都是因为⾯向对象的封装与多态。他们实现的思想都是先设定⼀个抽象的模型并从该模型派⽣出符合不同客户需求的各种⽅法,并加以封装。
简单⼯⼚模式可以与策略模式结合。
简单⼯⼚模式需要客户端认识⼯⼚类和抽象类的⽅法。
⽽策略模式简单⼯⼚模式的结合可以把客户端的判断封装在Context类的构造函数⾥,这样可以让客户端只需要认识 Context 类就⾏了,更降低了耦合度。
例如简单⼯⼚模式:
$a=Factory::func('123');
$a->show();
客户需要知道⼯⼚类的创建⽅法func与类名Factory.还需要知道返回的类继承的抽象类或者接⼝定义的⽅法show()的⽤法。
⽽策略模式中
$a=new Context(new aClass(123));
$a->show();
还是需要客户端认识Context类与传⼊构造函数的参数类,所以可以加以改造,将策略模式与简单⼯⼚模式结合起来,让构造函数接受⼀个条件变量,在构造函数中根据这个变量来决定产⽣的具体实例。
$a = new Context(123);
$a->show();
客户只需要认识Context类就可以了。
策略模式的重点在于让算法家族间的算法可以相互替换,引起的变化不会影响到使⽤算法的客户。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。