作者归档:admin

PHP设计模式笔记:使用PHP实现适配器模式

PHP设计模式笔记:使用PHP实现适配器模式

【意图】
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原来由于接口不兼容而不能一起工作的那此类可以一起工作【GOF95】

【适配器模式结构图】

类适配器

类适配器

对象适配器

对象适配器


【适配器模式中主要角色】
目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所期待得到的
源(Adaptee)角色:需要进行适配的接口
适配器(Adapter)角色:对Adaptee的接口与Target接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类

【适配器模式适用场景】
1、你想使用一个已经存在的类,而它的接口不符合你的需求
2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作
3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口(仅限于对象适配器)

【类适配器模式与对象适配器】
类适配器:Adapter与Adaptee是继承关系
1、用一个具体的Adapter类和Target进行匹配。结果是当我们想要一个匹配一个类以及所有它的子类时,类Adapter将不能胜任工作
2、使得Adapter可以重定义Adaptee的部分行为,因为Adapter是Adaptee的一个子集
3、仅仅引入一个对象,并不需要额外的指针以间接取得adaptee

对象适配器:Adapter与Adaptee是委托关系
1、允许一个Adapter与多个Adaptee同时工作。Adapter也可以一次给所有的Adaptee添加功能
2、使用重定义Adaptee的行为比较困难

【适配器模式与其它模式】
桥梁模式(bridge模式):桥梁模式与对象适配器类似,但是桥梁模式的出发点不同:桥梁模式目的是将接口部分和实现部分分离,从而对它们可以较为容易也相对独立的加以改变。而对象适配器模式则意味着改变一个已有对象的接口
装饰器模式(decorator模式):装饰模式增强了其他对象的功能而同时又不改变它的接口。因此装饰模式对应用的透明性比适配器更好。

【类适配器模式PHP示例】
类适配器使用的是继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 
<?php
/**
 * 类适配器模式的PHP简单实现2010-07-10 sz
 * @author 胖子 phppan.p#gmail.com  http://www.phppan.com                                               
 * 哥学社成员(http://www.blog-brother.com/)
 * @package design pattern
 */
 
/**
 * 目标角色
 */
interface Target {
 
    /**
     * 源类也有的方法1
     */
    public function sampleMethod1();
 
    /**
     * 源类没有的方法2
     */
    public function sampleMethod2();
}
 
/**
 * 源角色
 */
class Adaptee {
 
    /**
     * 源类含有的方法
     */
    public function sampleMethod1() {
        echo 'Adaptee sampleMethod1 <br />';
    }
}
 
/**
 * 类适配器角色
 */
class Adapter extends Adaptee implements Target {
 
    /**
     * 源类中没有sampleMethod2方法,在此补充
     */
    public function sampleMethod2() {
        echo 'Adapter sampleMethod2 <br />';
    }
 
}
 
class Client {
 
    /**
     * Main program.
     */
    public static function main() {
        $adapter = new Adapter();
        $adapter->sampleMethod1();
        $adapter->sampleMethod2();
 
    }
 
}
 
Client::main();
?>

【对象适配器模式PHP示例】
对象适配器使用的是委派

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
 
<?php
/**
 * 对象适配器模式的PHP简单实现 2010-07-10 sz
 * @author 胖子 phppan.p#gmail.com  http://www.phppan.com                                   
 * 哥学社成员(http://www.blog-brother.com/)
 * @package design pattern
 */
 
/**
 * 目标角色
 */
interface Target {
 
    /**
     * 源类也有的方法1
     */
    public function sampleMethod1();
 
    /**
     * 源类没有的方法2
     */
    public function sampleMethod2();
}
 
/**
 * 源角色
 */
class Adaptee {
 
    /**
     * 源类含有的方法
     */
    public function sampleMethod1() {
        echo 'Adaptee sampleMethod1 <br />';
    }
}
 
/**
 * 类适配器角色
 */
class Adapter implements Target {
 
    private $_adaptee;
 
    public function __construct(Adaptee $adaptee) {
        $this->_adaptee = $adaptee;
    }
 
    /**
     * 委派调用Adaptee的sampleMethod1方法
     */
    public function sampleMethod1() {
        $this->_adaptee->sampleMethod1();
    }
 
    /**
     * 源类中没有sampleMethod2方法,在此补充
     */
    public function sampleMethod2() {
        echo 'Adapter sampleMethod2 <br />';
    }
 
}
 
class Client {
 
    /**
     * Main program.
     */
    public static function main() {
        $adaptee = new Adaptee();
        $adapter = new Adapter($adaptee);
        $adapter->sampleMethod1();
        $adapter->sampleMethod2();
 
    }
 
}
 
Client::main();
?>

反转UTF8编码中文字符串的2种方法

反转UTF8编码中文字符串的2种方法

某天查手册时,看到strrev函数下面有一个 utf8_strrev函数的实现,觉得有些意思,于是自己使用mb开头的函数写了另一个实现。
【第一种方案】
使用正则匹配出所有的内容到数组,然后使用数组中的反转函数将整个数组反转,然后将数组转化成字符串
其代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
<?php
header("Content-type:text/html;charset=utf-8");
 
$str = "bb我是中国人aaaa";
 
/**
* 反转utf8的字符串,使用正则和数组实现
* @param string $str
* @return string
*/
function utf8_strrev($str){
  preg_match_all('/./us', $str, $ar);
  return implode('', array_reverse($ar[0]));                                                   
}
echo utf8_strrev($str), '<br />';

其中正则的两个修正符的说明如下:
u (PCRE_UTF8)
此修正符启用了一个 PCRE 中与 Perl 不兼容的额外功能。模式字符串被当成 UTF-8。本修正符在 Unix 下自 PHP 4.1.0 起可用,在 win32 下自 PHP 4.2.3 起可用。
s (PCRE_DOTALL)
如果设定了此修正符,模式中的圆点元字符(.) 匹配所有的字符,包括换行符。没有此设定的话,则不包括换行符。这和 Perl 的 /s 修正符是等效的。排除字符类例如 [^a] 总是匹配换行符的,无论是否设定了此修正符。

【第二种方案】
使用Multibyte String Functions实现
算出字符串在utf8ut编码下的长度,倒序取每个utf8字符,连接起来,返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
header("Content-type:text/html;charset=utf-8");
 
$str = "bb我是中国人aaaa";
 
/**
* 反转utf8的字符串,使用mb开头的函数
* @param string $str
* @return string
*/
function mb_strrev($str) {
    $len = mb_strlen($str, 'UTF-8');
    $string = '';
    for ($i = $len - 1; $i >= 0; $i--) {
       $string .= mb_substr($str, $i, 1, 'UTF-8');                                                         
    }
    return $string;
}
 
echo mb_strrev($str);

最后一句:多看手册

Google Adwords API开发环境问题

Google Adwords API开发环境问题

最近接手系统中Google Adwords API的开发,然后需要取广告系统的数据,当一切准备就绪后,自己写了代码,发现根本没有取到数据,到最后是有一些必要的扩展没有打开。
需要扩展列表如下:
【soap扩展】
如果soap扩展没有打开,则会报错如下:
Fatal error: This client library requires the SOAP extension to be activated. See http://php.net/manual/en/soap.installation.php for details. in aw_api\src\Google\Api\Ads\Common\Lib\SoapClientFactory.php on line 93
打开方式:在php.ini中将 extension=php_soap.dll前面的分号去掉

【openssl扩展】
如果opensslpss扩展没有找开,则会报错如下:
Warning: SoapClient::SoapClient() [soapclient.soapclient]: Unable to find the wrapper “https” – did you forget to enable it when you configured PHP? in aw_api\src\Google\Api\Ads\Common\Lib\AdsSoapClient.php on line 142
Warning: SoapClient::SoapClient() [soapclient.soapclient]: I/O warning : failed to load external entity “https://adwords.google.com/api/adwords/cm/v200909/CampaignService?wsdl” in aw_api\src\Google\Api\Ads\Common\Lib\AdsSoapClient.php on line 142

打开方式:在php.ini中将 extension=php_openssl.dll前面的分号去掉

【curl扩展】
如果curl扩展没有找开,则会报错如下:
Fatal error: Call to undefined function curl_init() in aw_api\src\Google\Api\Ads\Common\Util\AuthToken.php on line 103
打开方式:在php.ini中将 extension=php_curl.dll前面的分号去掉

其实到最后,发现这些本来就是应该打开的扩展,google使用https,这就必须要开启 openssl,我们使用wsdl,就必须要开启soap

是受http://blog.csdn.net/cooledit2730/archive /2010/05/22/5616134.aspx的启发,才发现有扩展没有打开的。一直以为是自己的代码问题。感谢