分类 灵魂思想 下的文章

面向对象的特性之一:封装。不需要知道具体如何实现的细节,只需要调用某个类的方法,得到预期的结果。尽可能少的使用public,降低成员的访问权限。可以更好降低类与类之间的耦合度。程序设计时,修改一个越弱耦合的类,对系统造成的影响就会越小,耦合度越低,越利于复用。这就是迪米特法则的根本思想。
依赖接口而不是依赖实现,在弱耦合、低权限的基础上,完全不需要关心接口的实现细节,这也就是依赖倒转原则。面向对象的原则和面向对象的特性是不对立的。
迪米特法则:如果两个类,不需要直接进行两个类之间的通信,那么,这两个类就不应该直接发生作用和求情,如果一个类在特定条件下需要调用另一个类,那么,可以通过第三个类来实现,转发这个调用。
是不是又用点像代理模式?代理模式是针对对象的,代理类实例化真实类,调用真实类的方法。而迪米特法则是一个类调用另一个类,然后这个另一个类再调用另另一个类。

模板方法模式,是最为常见,也是使用最为广泛的一种设计模式,很多程序猿都不知道,自己随便写的代码,也是一种设计模式。如果只能学习一种设计模式的话,那么就应该学习模板模式。
模板模式:在一个方法里定义算法的骨架,将一些步骤延迟到其子类。顾名思义,模板模式,就是有一个固定的,现成的模板,往里面套东西呗。比如PPT,WORD,EXCEL等,Microsoft为我们提供了大量的模板。可以直接套用,也可以略做修改。总之,比我们自己全新做要省很多事儿。
抽出多个类的共同特性,成为一个父类,父类根据需求封装好一个算法骨架,然后子类调用父类即可。
以PHP为代码环境,

<?php
class TestPaper{
    public $name;
    public $classes;
    public function __construct($name, $classes){
        $this->name = $name;
        $this->classes = $classes;
    }
    public function display(){
        echo '姓名:' . $this->name . ', 班级:' . $this->classes;
        $this->separate();
    }
    public function title1($answer){
        echo '题目一:******';
        echo '答案:' . $this->answer($answer);
        $this->separate();
    }
    public function title2($answer){
        echo '题目二:******';
        echo '答案:' . $this->answer($answer);
        $this->separate();
    }
    public function answer($answer){
        return $answer;
    }
    public function separate(){
        echo '<br>';
    }
}
class studentA extends TestPaper{
    public function __construct($name, $classes){
        parent::__construct($name, $classes);
    }
    public function answerTestPaper(){
        $this->display();
        $this->title1('C');
        $this->title1('B');
    }
}
class studentB extends TestPaper{
    public function __construct($name, $classes){
        parent::__construct($name, $classes);
    }
    public function answerTestPaper(){
        $this->display();
        $this->title1('A');
        $this->title1('D');
    }
}
$studentA = new studentA('小明', '一');
$studentA->answerTestPaper();
$studentB = new studentB('小红', '二');
$studentB->answerTestPaper();
?>

原型模式提取重复功能,避免了程序员喜欢复制粘贴的坏习惯。设计模式中的原型模式就是,用原型实例指定创建对象的重力,通过拷贝这些原型来创建新的对象从一个对象再创建另外一个可定制的对象,而且不需要知道创建的任何细节。
浅复制 VS 深复制:
浅复制是对数字,字符串等类型进行传值复制,而对对象来讲是引用复制,即只是对内存地址进行赋值而不是新建一个对象的变量。在浅复制中,对一个对象的属性改变,另一个对象的该属性也会被改变,类比于C语言的指针,PHP在调用方法时&$var的传递。
以PHP为代码环境。

<?php
//家庭类
class Home{
    public $money;
    public function __construct($money){
        $this->money = $money;
	}
}
//家庭成员类
class member{
    public $id;
    public $name;
    public $obj;
    public function __construct($id, $name, Home $obj){
        $this->setId($id);
        $this->setName($name);
		$this->obj = $obj;
    }
    public function setId($id){
        $this->id = $id;
    }
	public function setName($name){
        $this->name = $name;
    }
    public function display(){
	    echo 'ID为' . $this->id . ',名称为' . $this->name . ',资产为' . $this->obj->money . '<br>';
    }
	public function __clone(){
        //深度复制(克隆),因为克隆只能克隆数字,字符串等,对对象变量是引用传值。	
        $this->obj = clone $this->obj;
    }
}
//客户端/接口
$obj1 = new member(1, '小轩', new Home('10000'));
$obj1->display();
$obj2 = clone $obj1;
$obj2->setId(2);
$obj2->setName('小玮');
$obj2->obj->money = 2000;
$obj2->display();
//根据这句输出可以看到,对象1和对象2值是不一样的,删掉上面的注释部分再看,又是一样的了,这就是深复制和浅复制。
$obj1->display();
?>

工厂方法:定义一个工厂接口,用来创建产品对象,将实际创建工作推迟到子类当中。
工厂方法来源于简单工厂模式,是简单工厂模式的一个衍生品。核心的工厂类不再进行类的实例化,核心工厂类不再负责产品的创建,核心的工厂类只负责子类的接口,使核心工厂类抽象化,成为一个抽象工厂。
工厂方法的优点:在简单工厂模式的基础上再次对核心工厂类进行抽象,在需要添加新的产品时,更好的依赖于开放-封闭原则,不需要修改具体的工厂角色即可扩展。
场景:简单计算器。以PHP为代码实现环境。
简单工厂模式:

<?php
class Calculator{
    public $numberA;
    public $numberB;
    public $result;
    public function returnResult(){

    }
}
class Add extends Calculator{
    public function __construct($a, $b){
        $this->numberA = $a;
        $this->numberB = $b;
    }
    public function returnResult(){
        $this->result = $this->numberA + $this->numberB;
        return $this->returnResult();
    }
}
class Sub extends Calculator{
    public function __construct($a, $b){
        $this->numberA = $a;
        $this->numberB = $b;
    }
    public function returnResult(){
        $this->result = $this->numberA - $this->numberB;
        return $this->returnResult();
    }
}
class Factory{
    public function calculatorFactory($operator, $numberA, $numberB){
        $obj = '';
        switch($operator){
            case '+':
                $obj = new Add($numberA, $numberB);
                break;
            case '-':
                $obj = new Sub($numberA, $numberB);
                break;
        }
        $result = $obj->returnResult();
        return $result;
    }
}
//客户端/接口
$operation = isset($_GET['operation']) ? $_GET['operation'] : '+';
$numberA = $_GET['numberA'];
$numberB = $_GET['numberB'];
$obj = new Factory();
echo $obj->calculatorFactory($operation, $numberA, $numberB);
?>

工厂方法:

<?php
class Calculator{
    public $numberA;
    public $numberB;
    public $result;
    public function returnResult(){}
}
class Add extends Calculator{
    public function __construct($a, $b){
        $this->numberA = $a;
        $this->numberB = $b;
    }
    public function returnResult(){
        $this->result = $this->numberA + $this->numberB;
        return $this->returnResult();
    }
}
class Sub extends Calculator{
    public function __construct($a, $b){
        $this->numberA = $a;
        $this->numberB = $b;
    }
    public function returnResult(){
        $this->result = $this->numberA - $this->numberB;
        return $this->returnResult();
    }
}
class Factory extends Calculator{
    public static function create($class, $numberA, $numberb){
        return new $class($numberA, $numberb);
    }
}
//客户端/接口
$operator = isset($_GET['operation']) ? $_GET['operation'] : '+';
$numberA = $_GET['numberA'];
$numberB = $_GET['numberB'];
switch($operator){
    case '+':
        $class = 'objAdd';
        break;
    case '-':
        $class = 'objSub';
        break;
}
$obj = Factory::create($class, $numberA, $numberb);
echo $obj->returnResult();
?>

简单工厂模式VS工厂方法模式:
简单工厂的选择在工厂类,

代理模式,是为其他对象提供一种代理以控制对这个对象的访问,代理模式是设计模式的一种。应用较为广泛,是一个对象需要访问另一个对象,出于某种原因或目的,在两个对象之间添加了一个中间对象。A对象访问B对象的方法,B对象的该方法实际是调用的C对象的方法,间接的完成了A对象对C对象的访问。这种模式叫做代理模式。
以PHP为代码环境,实现设计模式中的代理模式。

<?php
abstract class Subject(){
abstract class Subject(){
    public function actionA();
	public function actionB(){;
    public function actionC();
}
class Substance implements Subject(){
    public function actionA(){
        echo '方法A的实现';	
	}
	public function actionB(){
        echo '方法B的实现';
	}
    public function actionC(){
	    echo '方法C的实现';
    } 
}
class Proxy implements Subject(){
    $protected $obj;
	public function __construct(){
        $obj = new Substance();
    }
    public function actionA(){
        $this->obj->actionA;
    }
    public function actionB(){
        $this->obj->actionB;
    }
    public function actionC(){
	    $this->obj->actionC;
    } 
}
//客户端/接口
$obj = new Proxy();
$obj->actionA();
$obj->actionB();
$obj->actionC();	
}
?>

代理模式的使用场景:(整理自大话设计模式一书)
第一、远程代理,为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
第二、虚拟代理,是根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的对象。
第三、安全代理,用来控制真实对象的访问权限。
第四、智能指引,是指当调用真实对象时,代理处理另外一些事情。(我的理解是,比如底层有一个封装好的Mysql类,在上层应用层读取数据库时,先经过一个代理类,可以检查数据完整性,参数合法性,计数器等等,然后由代理类调用真实的Mysql类)