深入PHP面向对象、模式与实践

澳门新葡亰娱乐在线 6

澳门新葡亰娱乐在线,3 生成对象

3、代理模式:(Proxy)
用代理类来调用主类的方法,还可以对其前后添加修改,为AOP常用方法。

3.4 平行模式

当使用工厂/抽象模式必须要制定具体的创建者(需求方).

平行模式和抽象模式的模型图一致,但代码实现不一样.

抽象模式中父类均为抽象类,而平行模式中,所以类都为普通类,方便父类的实例化.

在这里列出显示印象笔记类的实现代码

class Show_Evernote{
    private $内容;
    private $账号;
    private $评论;

    function __construct(内容,账号,评论){
        $this->内容 = 内容;
        $this->账号 = 账号;
        $this->评论 = 评论;
    }

    function get_内容(){
        return clone $this->内容);
    }

    function get_账号(){
        return clone $this->账号);
    }

    function get_评论(){
        return clone $this->评论;
    }
}

//使用
$factory = new Show_Evernote( 
    new 新浪微博内容(),
    new 新浪微博账号(),
    new 新浪微博评论()
);

印象笔记控件类->显示印象笔记 = $factory;

其实大家可以发现,原型模式只不过只在最顶层类中包装了一下各组件子类而已,然而这样可以轻松的组合他们,例如实现一个显示新浪微博内容,但要显示开发者头条账号的需求?

21、访问者模式:(Visitor)

3.3 抽象模式

RLGL!!!.印象笔记不只要显示新浪微博内容!!!还要显示我的新浪账号,还要该微博啊!!卧槽~憋着急,吻我.

工厂模式主要用于生产一一对应的产品方和需求方,而抽象模式要做的是一个需求方(印象笔记_显示新浪微博),要多个工厂(把需求方抽象为多个需求方),例如提供新浪内容的工厂,提供新浪账号的工厂.提供微博内容的评论的工厂等.

澳门新葡亰娱乐在线 1

代码:

abstract class Show_Evernote {
    abstract function get_header_text();
    abstract function get_context();
    abstract function get_footer_text();
    abstract function get_user();
    abstract function get_comment();

}

class 显示新浪微博 extends Show_Evernote{
    function get_header_text(){...};
    function get_context(){new 新浪微博_内容;}
    function get_footer_text(){...};
    function get_user(){new 新浪微博_账号 ;}
    function get_comment(){new 新浪微博_评论;}
}

//使用
印象笔记控件类->内容 = 显示新浪微博->get_context;
印象笔记控件类->账号 = 显示新浪微博->get_context;
...

适用:需要多个复杂的部分组合起来的返回对象。

4.3 外观模式

即给外部系统提供清晰接口

例如当Model层写得很混乱,但是里面的方法还能用,那我们的Controller层应该列举一些清晰的访问方法来供View层访问.外观模式,强调的是清晰的访问接口.

直接看本文估计比较枯燥无聊,因为没图😝,建议对设计模式有兴趣的先看看上面的博文,或者基础比较好可直接移到最底下看下我的各模式一句话概括总结,有什么意见建议欢迎提出~~~~

1 语法

4、单例模式:

4.2 装饰模式

装饰模式,首先洗脚男,洗发男,捶背男都是人,但是如果,一个男的又捶背,又洗发,这怎么玩?.add_man两次?这不科学吧,来给这些男的装饰一下吧~

澳门新葡亰娱乐在线 2

abstract class 人{
    ...
    abstract function get_well();
}   

class 男 extends 人 {
    //无论你是神马男,服务你,你就能获得10点舒服度.
    private $well = 10;
    function get_well(){
        return $this->well();
    }
}

abstract class 装饰男类型 extends 人 {
    protected $人;
    function __construct(人 $人){
        $this->人 = $人;
    } 
}

class 捶背装饰 extends 类型男装饰{
    function get_well(){
        return $this->人->get_well()+30;
    }
}

class 洗发装饰 extends 类型男装饰{
    function get_well(){
        return $this->人->get_well()+20;
    }
}

class 洗褪装饰 extends 类型男装饰{
    //老子不喜欢别人碰我的毛裤.
    function get_well(){
        return $this->人->get_well()-20;
    }
}

//创建捶背,能给予的舒服指数 - -嘻嘻.
$人 = new 捶背装饰(new 男);
$人->get_well(); // 10+30 = 40

//来来来,全能选手,捶背、洗发、洗腿一起来
$人 = new 洗脚装饰(new 洗发装饰(new 捶背装饰(new 男()))); //10+30+20-20 = 40,注意顺序,由里到外执行.

装饰模式,既(组合+继承),基类方法一定要尽量少,不然子类可能有它不该有的方法.直接类继承,她只可能是一种形态,而她的多种形态可能一并拥有的时候,应该运用组合.

继承即单一多态,组合既多种多态.

这个例子中,你可以添加女,然后把装饰男类型改为装饰通用类型,但每个get_well()都要多一个判断是男还是女(如果给予的舒服程度不一样).

这只是确保不可能出现在,之外的第三种人,如果基类为动物,给予服务的可能是鸡,鹅,鸭,那么装饰类型应该运用工厂模式,动物形态和装饰形态一一对应.方便拓展.

除了服务类型,服务男的样子也很重要,这就多了一种装饰,现在有装饰男类型相貌男类型,这种情况怎么破,其实类似.

澳门新葡亰娱乐在线 3

//如何获取捶背的帅哥麦?,
$人 =new 男类型(new 捶背(new 帅哥麦(new 男())));

本文是对各处设计模式示例的总结概括和简化,主要参考

2 模式

将多个类复合起来管来,不同类的组装,组装顺序不同等因素都可能导致结果不同。

5.4 命令模式

例子为Web页面的login和feed_back,假如都需要使用ajax提交,那么问题来了,将表单封装好提交上去,得到了返回结果.如何根据返回结果跳转不同的页面?.

有些同学就说了,login和feed_back各自写一个方法憋,提交的时候调用各自的方法.

然后再来个logout命令..增加..删除..命令怎么办..

命令模式比较适合命令执行例如登陆,反馈等简单只需要判断是否成功的任务

澳门新葡亰娱乐在线 4

命令:

abstract class Command{
    abstract function execute(Conmmand_Context $context);
}

class Login_Command extends Command{
    function execute(CommandContext $context){
        $managr =Register::getAccessManager();
        $user = $context->get("username");
        $pass = $context->get('pass');
        $user_obj = $manager->login($user,$pass);
        if(is_null($user_obj)){
            $context->setError($manager->getError());
            return false;
        }
        $context->addParam("user",$user_obj);
        return true;
    }
}

部署命令的调用者

class Command_Facotry{
    public function get_command($action){
        $class = UCFirst(strtolower($action))."_Command";
        $cmd = new $class();
        return $cmd;
    }

}

客户端

class Controller{
    private $context;
    function __construct(){
        //Command_Context主要用来存储request和params
        $this->context =new Command_Context();
    }
    function process(){
        $cmd Command_Factory::get_commad($this->context->get('action'));
        if(!$cmd-execute($this->context)){
            //错误处理
        }else{
            //成功 分发视图
        }
    }
}

使用

$controller =new Controller();
$context = $controller->get_context();
$context->add_param('action','login');
$context->add_param('username','404_k');
$context->add_param('pass','123456');
$controller->process();

 

1.1 基础语法

clone

需要操作原对象,但又不想影响原对象.

$K_back = clone $K;

基本数据类型和数组都为真复制,即为真副本,当属性为对象时,为假复制,改变副本仍会影响原对象.解决方案:

//在原对象中添加
function __clone(){
    $this->对象 = clone $this->对象
}

__clone在clone前自动触发,可以执行一些在备份前的属性操作.

&传递引用

方法引用传递,改变源对象

function set_K(& $K){...}

function & get_K(){...}

static延迟静态绑定

应用场景:Dog类和Person类都需要一个返回实例化的方法,Dog类和Person类都继承于Animal抽象类.

abstract class Animal{
    public static function create(){
        //实例化调用类
        return new static();
    }
}

class Person extends Animal{...}

//返回Person实例化类
Person::create();

拦截器

  1. __get($property),访问未定义的属性时调用.
  2. __set($property,$value),给未定义的属性赋值时被调用.
  3. __isset($property),对未定义属性调用isset()方法时调用.
  4. __unset($property),对未定义属性调用unset()方法时调用.
  5. __call($method,$arg_array),调用未定义方法时调用.__call很有用,但要慎用,因为太灵活.应用场景:有一个专门打印Person类信息的Person_Writer类,如果通过Person类调用Person_Writer类.

    //Person委托Person_Writer类处理打印事务.
    class Person {
        private $writer;
        ...
    
        function __call($method_name,$args){
            if(methood_exists($this->wirter,$method_name)){
                return $this->writer->$method_name($this);
            }
        }
    
        //高级__call写法,当委托方法参数不确定时使用.
        function __call($method_name,$args){
            //当然这里这样写法意义不大,但是call一般都是用call_user_func_array调用
            $args = $this ;
            if(methood_exists($this->wirter,$method_name)){
                return call_user_func_array(
                    array($this->writer,$method_name),$args);
                )
            }
        }
    
    }
    

回调函数

应用场景:
3个类,Product类,Product_Sale类,Product_Totalizer类,要实现:当卖出Product总共价格超过指定金额时,输出警告.

//Product
class Product {
    public $name;
    public $price;
}

//Product_Sale
class Product_Sale {
    private $callbacks;

    //记录回调函数
    function register_callback ($callback) {
        if(! is_callback($callback)){
            thow new Exception('callback not callable');
        }
        $this->callbacks[] = $callback;
    }

    //执行回调函数
    function sale ($product){
        print "{$product->name} : 处理中 n";
        foreach($this->callbacks as $callback){
            call_user_func($callback , $product);
        }
    }
}

//Produce_Totalizer
class Produce_Totalizer {
    static function warn_amount ($amt) {
        $count = 0;
        return function ($produce) use ($amt , &count) {
            $count += $produce->price;
            print " count : {count}n"
            if($count>$amt){
                print "quot;超过指定金额{$amt}啦~";
            }
        };
    }
}

//模拟场景
$product_sale = new Produce_Sale();
//指定报警金额为8块
$product_sale = register_callback(Produce_Totalizer::warn_amount(8)); 

//卖商品
$product_sale->sale(new Product("Durex",6));
$product_sale->sale(new Produce("Jissbon",5));

//输出结果
Durex : 处理中
    count :6 

Jissbon : 处理中 
    count: 11

超过指定金额8块啦~

get_class()instanceof

get_class(类)用于判断是否精准等于类名;

instanceof 可以判断是否其本身或继承于某父类.

类中的方法和类中的属性

get_class_methods('类名'):获取类中所有方法.

get_class_vars('类名'):获取类中所有public参数;

反射API

封装一个对象复杂的实现过程,使用相同接口创建不同的子类对象,便于扩展。

2.1 组合

问题:课堂类被演讲类和研讨会类继承着.但是演讲类和研讨类都要实现一次性计费和上N次课计费的方法.和输出计算的方式.

解决方案1:
在课堂类中添加计算一次性付费的方法,上N次课的计费方法和输出计算方式的方法.

解决方案2: 运用组合,将处理计费和输出计算方式单独封装为一个计费策略类.

澳门新葡亰娱乐在线 5

abstract class Cost_Strategy {
    protected $duration;
    abstract function cost ();
    abstract function charge_type();

    public __construct($duration){
        $this->duration = $duration;
    }
}

class Timed_Const_Strategy extends Cost_Stratedy {
    function cost () {
        //上一次课给5块钱- -.
        return $this->duration * 5;
    }

    function charge_type(){
        return "多次课结算";
    }
}

class Fixed_Const_Strategy extends Cost_Stratedy {
    function cost (){
        return 30 ;
    }

    function charge_type(){
        return "一次性课结算";
    }
}

abstract class Leason {

    private $cost_strategy;

    public __construct(Const_Strategy $cost_strategy){
        $this->cost_strategy = $cost_strategy;
    }

    function __call($method_name,$args){
        $args = $cost_strategy ;
        if(methood_exists($this->cost_strategy,$method_name)){
            return call_user_func_array(
                array($this->writer,$method_name),$args);
            )
        }
    }
}

//运用
$leasons[] = new Seminar(new Timed_Const_Strategy(4));
$leasons[] = new Lecture(new Fixed_Const_Strategy(null));

foreach ($leasons as $leason){
    print "leason charge : {$leason->const()}";
    print "charge_type : {$leason->charge_type()}"
}

leason charge 20. charge_type : 多次课结算;
leason charge 30. charge_type : 一次课结算;

组合既委托.同级委托.

继承既父子关系.

6、抽象工厂模式:

3.1 单例模式

确保系统中只有唯一一个用例.例如系统配置文件.

重点

1: 构造方法私有.

2: 类本身包含自己的实例化属性.

澳门新葡亰娱乐在线 6

class Preferences {
    private static $instance;
    private function __construct(){ ... }

    public static function get_instance(){
        if(empty(self::$instance)){
            self::$instance = new Preferences();
        }
        return self::$instance;
    }
    ...
}

//使用
$preferences = Preferences::get_instance();

9、外观模式:(Facade)
为了解决类与类之间的依赖关系,将多各类的关系封装在另一个类中,降低类间的耦合度。

5 执行任务

7、建造者模式:(builder)

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图