标签归档:面向对象

PHP设计模式笔记:使用PHP实现模板方法模式

PHP设计模式笔记:使用PHP实现模板方法模式

【意图】
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method 使得子类可以在不改变一个算法的结构的情况下重定义该算法的某些特定的步骤【GOF95】

【模板方法模式结构图】

Template Method

Template Method

【模板方法模式中主要角色】
抽象模板(AbstractClass)角色: 定义一个或多个抽象方法让子类实现。这些抽象方法叫做基本操作,它们是顶级逻辑的组成部分。
定义一个模板方法。这个模板方法一般是一个具体方法,它给出顶级逻辑的骨架,而逻辑的组成步骤在对应的抽象操作中,这些操作将会推迟到子类中实现。同时,顶层逻辑也可以调用具体的实现方法

具体模板(ConcrteClass)角色:实现父类的一个或多个抽象方法,作为顶层逻辑的组成而存在。

每个抽象模板可以有多个具体模板与之对应,而每个具体模板有其自己对抽象方法(也就是顶层逻辑的组成部分)的实现,从而使得顶层逻辑的实现各不相同。

【模板方法模式适用场景】
1、一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
2、各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
3、控制子类扩展。

【模板方法模式与其它模式】
1、策略模式(strategy模式):模板方法使用继承来改变算法的部分,策略模式使用委托来改变整个算法。区别在于封闭的变化不同,一个变化的部分,一个变化的是整体。
2、工厂方法模式(factory method模式):Factory Method模式常被模板方法调用。
【模板方法模式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
<?php
/**
 * 模板方法模式简单示例 2010-09-12 sz
 * @author phppan.p#gmail.com  http://www.phppan.com                                                       
 * 哥学社成员(http://www.blog-brother.com/)
 * @package design pattern
 */
 
/**
 * 抽象模板角色
 * 定义抽象方法作为顶层逻辑的组成部分,由子类实现
 * 定义模板方法作为顶层逻辑的架子,调用基本方法组装顶层逻辑
 */
abstract class AbstractClass {
 
    /**
     * 模板方法 调用基本方法组装顶层逻辑
     */
    public function templateMethod() {
        echo 'templateMethod begin.<br />';
        $this->primitiveOperation1();
        $this->primitiveOperation2();
        echo 'templateMethod end.<br />';
    }
 
    /**
     * 基本方法1
     */
    abstract protected function primitiveOperation1();
 
     /**
     * 基本方法2
     */
    abstract protected function primitiveOperation2();
}
 
/**
 * 具体模板角色
 * 实现父类的抽象方法
 */
class ConcreteClass extends AbstractClass{
    /**
     * 基本方法1
     */
    protected function primitiveOperation1() {
        echo 'primitiveOperation1<br />';
    }
 
     /**
     * 基本方法2
     */
    protected function primitiveOperation2(){
        echo 'primitiveOperation2<br />';
    }
 
}
 
/**
 * 客户端
 */
class Client {
 
     /**
     * Main program.
     */
    public static function main() {
        $class = new ConcreteClass();
        $class->templateMethod();
    }
}
 
Client::main();
?>

【模板方法模式】
模板方法是一种代码复用的基本技术,模板方法导致一种反射的控制结构,这指的是一个父类调用子类的操作。
其实现过程:准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。

【重构的原则】
重构时应当遵守的原则是:将行为以是移到结构的高端,而将状态尽量移动到结构的低端。
Auer曾在文献【AUER95】中指出:
1、应当要所行为而不是状态定义一个类。
2、在实现行为是,是用抽象状态而不是用具体状态。
3、给操作划分层次。
4、将状态的确认推迟到子类中。在父类中,如果需要状态属性的话,可以调用抽象的取值方法,而将抽象的取值方法的实现放到具体子类中。
如果可以遵守以上的而,那么就可以在等级结构中将接口与实现分离,将抽象与具体分离,从而保证代码可以最大限度的被复用。

PHP帮助手册拾遗三:类与对象

PHP帮助手册拾遗:类与对象

1、__autoload函数
__autoload函数定义时必须包含一个参数,否则会显示如下错误:
Fatal error: __autoload() must take exactly 1 argument

在 __autoload 函数中抛出的异常不能被 catch 语句块捕获并导致致命错误。

2、父类的构造方法调用
如果子类中定义了构造函数则不会暗中调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct()。这里python和php一样

3、父类的析构方法调用
和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。
析构函数在脚本关闭时调用,此时所有的头信息已经发出。
试图在析构函数中抛出一个异常会导致致命错误。

4、访问限制
var与public在类中的变量定义相同,但是在php5的php5.1.3会生成一个E_STRICT警告
方法如果没有设置访问控制,则将默认设置为public

5、构造方法
PHP提交两种构造方法,以类名和__construct,当类中没有__construct方法时,PHP会调用类名函数,但是如果存在__construct时,不管其访问控制是什么,都不会调用类名函数。
如下所示代码:

1
2
3
4
5
6
7
8
9
10
11
class Demo {
    public function Demo() {
       echo 'Demo function';
    }
 
    private function __construct() {
       echo '__construct function';
    }
}
 
$demo = new Demo();

运行会报错:Fatal error: Call to private Demo::__construct() from invalid context
ps:上面的这个问题是ben前辈提出的,感谢ben前辈昨天的指导

6、静态变量
PHP5.3以后,可以使用变量引用类,但是这个变量不能是关键字(如self,parent,static等)。如下所示代码:

1
2
3
4
5
6
class Demo {
    public static $my_static = 'Demo';
}
 
$classname = 'Demo';
print $classname::$my_static . "\n"; // As of PHP 5.3.0

7、接口
接口可以有常量,不能有变量,并且常量在其子类中无法重载
如下所示代码:

1
2
3
4
5
6
7
8
9
10
11
interface Base {
    const constant = 'constant value';
    public $var = "test var";
}
 
class Foo implements Base {
 
}
 
echo Base::constant;
echo Base::$var;

以上代码报错为:Fatal error: Interfaces may not include member variables
注释掉对变量的操作后可以正常打印常量中存放的值。
8、对象迭代
在PHP5中,使用foreach,遍历一个对象,可以访问这个对象的所有可以访问的属性
如果要自定义迭代器,可以通过实现一个叫Iterator的接口来实现
9、单例模式
单例模式(singleton模式)在实现过程中,需要考虑__clone方法。
10、对象与引用
PHP5之后,对象在默认情况下是以引用的方式传递的。

妙解Hibernate 3.x——叩响面向对象思想之门 读书笔记

妙解Hibernate 3.x——叩响面向对象思想之门 读书笔记
在今年过生日的时候公司送了这本书给我,是部门老大挑的
找些时间看了下,由于在工作中并没有用到Hibernate,所有大部分内容没有看,
只看了前面的几章,当看到第三章,觉得仅第三章,这本书都值得一看(后面的章节由于用不到hibernate,只是简单过一遍)
第三章,看了不下三遍,觉得自己在某些地方还是看不懂,可能是对于面向对象的一些东西的理解还不够

使用继承、委托看待和拆解设计模式

将对象做虚,做软,不要被“变因”硬邦邦地绑住
—-封装变化

生成对象时,不直接new,才不会被具体对象绑死,此原则在学习面向对象中的创建模式有很好的指导作用
—-封装创建过程

模板方法与策略都将算法提取出来,只不过模板方法使用的是继承,策略使用的是委托
—-其实就这种模式,其本质应该是在其封装的变化的不同,模板方法是封装部分算法,而策略是封装整个算法
策略的重用性会高一些,只是需要付出一些额外的代价

回归最根本的面向对象思想:封装、继承、多态、委托

关于设计模式的学习:
1、接口、抽象类、具体对象是软件“软性”的指标之一,可按照实际需要的稳定性加以调整
2、研究模式三部曲:明确要解决的问题–>怎么解–>套用模式所带来的好处和副作用
3、从代码级看设计模式:
去掉new
去掉if/switch…case.
去掉重复的代码
4、开始接触一个新的设计模式,如果领导不到使用该模式的好处,不妨动手写一段程序,再来跟书中的实例进行比较
5、不时和自己的心灵对话—用自己的话来诠释模式,哪怕是简短的一句话,一个口诀,一个比喻
Builder 单一制程,不同风格
Sigleton just only one
Prototype 复制
Adapter 转换
Composite Tree
Decorator Dynamic composing behavior
Facade 简化
Proxy 本体/分身相互成就
Momento 借尸还魂
Strategy 替换多变的内部行为
6、不同的设计模式可能极其相似,搞不清是因为没有彻底掌握,这需要时间的积累
7、设计模式老是记不住,无法突破,那就放弃,过段时间再来温故知新
8、运用面向对象和设计模式,切忌矫枉过正,不要好处没得到,却被过度设计给弄复杂了

从Think in Data 到Think in Object

–EOF–