参考网站

单例模式:

废话不多说,我们直接上代码:

<?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类就可以了。

策略模式的重点在于让算法家族间的算法可以相互替换,引起的变化不会影响到使用算法的客户。

 


oop的三种设计模式(单例、工厂、策略)的更多相关文章

  1. php : MVC 演示(使用单例工厂)

    此例子是MVC的简单应用, 要达到的效果如下: 用户列表: 姓名 年龄 学历 兴趣 出生地 账号创建时间 操作 keen 20 高中 篮球,足球 广东 2016-11-08 10:00:31 删除 a ...

  2. 如何将业务代码写得像诗一样(使用注解+单例+工厂去掉一大波if和else判断)

    1.订单控制器,提供一个根据商品id和银行渠道id计算商品折后价格的接口: import org.springframework.web.bind.annotation.GetMapping; imp ...

  3. 三、singleton(单例化)一个对象的几种方法

    方案一:私有化构造器,通过static final域 @Test public void test13() { A215 a=A215.a; A215 b=A215.a; System.out.pri ...

  4. PHP常用的三种设计模式

    本文为大家介绍常用的三种php设计模式:单例模式.工厂模式.观察者模式,有需要的朋友可以参考下. 一.首先来看,单例模式 所谓单例模式,就是确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实 ...

  5. javascript学习(9)——[设计模式]单例

    单例模式,相信大家对此都不陌生,我们主要讲下javascript中几个比较常见的设计模式: (1).普通的单体 (2).具有局部变量的强大单体 (3).惰性单体 (4).分支单体 下面我们就一一进行介 ...

  6. java设计模式--单例

    GOF23(group of four)---由4个大牛总结的JAVA23种常用的设计模式,归根结底都是为了代码的可扩展性. 设计模式中一种比较重要的思想就是:开闭原则,尽量做到对扩展开放,对修改关闭 ...

  7. C#设计模式——单例

    单例模式是设计模式中最简单的形式之一.这一模式的目的是使得类的一个对象成为系统中的唯一实例.对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任 ...

  8. php设计模式-单例

    单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例. <设计模式>对此的定义:保证一个类仅有一个实例,并提供一个访 ...

  9. Java设计模式—单例设计模式(Singleton Pattern)全然解析

    转载请注明出处:http://blog.csdn.net/dmk877/article/details/50311791 相信大家都知道设计模式,听的最多的也应该是单例设计模式,这种模式也是在开发中用 ...

随机推荐

  1. c++ UDP套接字服务器端代码示范

    c++ UDP套接字服务器端代码示范 #include<winsock2.h> //包含头文件 #include<stdio.h> #include<windows.h& ...

  2. 用python玩推理游戏还能掌握基础知识点,有趣又充实,你不试试吗?

    可能更多的人依然还在苦苦的学python各种知识点,但其实同样很多人,玩着游戏就把python学会了.     用python玩推理游戏,是这份python教程中的12个游戏的其中之一. 有关这份Py ...

  3. Tensorflow 中(批量)读取数据的案列分析及TFRecord文件的打包与读取

    内容概要: 单一数据读取方式: 第一种:slice_input_producer() # 返回值可以直接通过 Session.run([images, labels])查看,且第一个参数必须放在列表中 ...

  4. springboot集成jpa操作mybatis数据库

    数据库如下 CREATE TABLE `jpa`.`Untitled` ( `cust_id` bigint() NOT NULL AUTO_INCREMENT, `cust_address` var ...

  5. hello python week one

    python的注释 好的pytho程序员不一定非要追求 代码的简短,代码的可读性也是至关重要的 与用户交互 输入 input 会将输入内容转化为字符串 输出 print 格式化输出 %d %s 占位符 ...

  6. Ubuntu图形界面root登录出现“sorry, that didn't work please try again”

    ssh登录主机执行下vim /etc/pam.d/gdm-autologin 注释行 "auth requied pam_succeed_if.so user != root quiet s ...

  7. 如何用Tesseract做日文OCR(c#实现)

    首先做一下背景介绍,Tesseract是一个开源的OCR组件,主要针对的是打印体的文字识别,对手写的文字识别能力较差,支持多国语言(中文.英文.日文.韩文等).是开源世界里最强的一款OCR组件.当然和 ...

  8. 【asp.net core 系列】14 .net core 中的IOC

    0.前言 通过前面几篇,我们了解到了如何实现项目的基本架构:数据源.路由设置.加密以及身份验证.那么在实现的时候,我们还会遇到这样的一个问题:当我们业务类和数据源越来越多的时候,我们无法通过普通的构造 ...

  9. 基础的markdown用法

    首先推荐一款在线的markdown编辑器:Editor.md 一篇博客里面就是文字与图片的集合.markdown其实就是编辑文字,插入图片的工具.对于大多数人来说,学习几个标签就可以了. 标题 #** ...

  10. java普通对象和json字符串的互转

    一.java普通对象和json字符串的互转 java对象---->json 首先创建一个java对象: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1 ...