Rumah > hujung hadapan web > tutorial js > Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

WBOY
Lepaskan: 2016-05-16 15:15:19
asal
1215 orang telah melayarinya

1 Tatabahasa

1.1 Tatabahasa Asas

klon

Perlu mengendalikan objek asal, tetapi tidak mahu menjejaskan objek asal.

Salin kod Kod adalah seperti berikut:

$K_back = klon $K;

Kedua-dua jenis data asas dan tatasusunan adalah salinan benar, iaitu, salinan benar Apabila atribut adalah objek, ia adalah salinan palsu tetap akan menjejaskan objek asal

//在原对象中添加
function __clone(){
  $this->对象 = clone $this->对象
} 
Salin selepas log masuk
__klon dicetuskan secara automatik sebelum pengklonan dan boleh melakukan beberapa operasi atribut sebelum sandaran.

2. & rujukan lulus

Melalui rujukan kaedah, menukar objek sumber

Salin kod Kod adalah seperti berikut:
set fungsi_K(& $K){...}
fungsi & dapatkan_K(){...}

3. ikatan statik tertunda statik

Senario aplikasi: Kedua-dua kelas Anjing dan kelas Orang memerlukan kaedah yang mengembalikan instantiasi Kedua-dua kelas Anjing dan kelas Orang mewarisi daripada kelas abstrak Haiwan.

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

class Person extends Animal{...}

//返回Person实例化类
Person::create();
Salin selepas log masuk
4

__get($property), dipanggil apabila mengakses sifat yang tidak ditentukan.

__set($property,$value), dipanggil apabila memberikan nilai kepada sifat yang tidak ditentukan.

__isset($property), dipanggil apabila memanggil kaedah isset() pada sifat yang tidak ditentukan.
__unset($property), dipanggil apabila memanggil kaedah unset() pada sifat yang tidak ditentukan.
__call($method,$arg_array), dipanggil apabila memanggil kaedah yang tidak ditentukan.
__call sangat berguna, tetapi gunakannya dengan berhati-hati kerana ia terlalu fleksibel.
Senario aplikasi: Terdapat kelas Person_Writer yang secara khusus mencetak maklumat kelas Person Jika kelas Person_Writer dipanggil melalui kelas Person.

//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);
      )
    }
  }

} 
Salin selepas log masuk
5. Fungsi panggil balik

Senario aplikasi: 3 kelas, kelas Produk, kelas Product_Sale, kelas Product_Totalizer, akan dilaksanakan: apabila jumlah harga jualan Produk melebihi jumlah yang ditentukan, amaran akan dikeluarkan.

//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 "超过指定金额{$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块啦~
Salin selepas log masuk
6. get_class() dan instanceof

get_class(class) digunakan untuk menentukan sama ada ia betul-betul sama dengan nama kelas;

instanceof boleh menentukan sama ada ia sendiri atau mewarisi daripada kelas induk.

7. Kaedah dalam kelas dan atribut dalam kelas

get_class_methods('class name'): Dapatkan semua kaedah dalam kelas.
get_class_vars('class name'): Dapatkan semua parameter awam dalam kelas;


8. API Refleksi

2 Mod

2.1 Gabungan

Masalah: Kelas bilik darjah diwarisi oleh kelas kuliah dan kelas seminar Walau bagaimanapun, kelas kuliah dan kelas seminar kedua-duanya perlu melaksanakan kaedah pengebilan sekali dan kelas N.

Penyelesaian 1: Tambahkan kaedah untuk mengira pembayaran sekali, kaedah untuk mengecaj N pelajaran dan kaedah untuk mengeluarkan kaedah pengiraan dalam kelas kelas.

Penyelesaian 2: Gunakan gabungan untuk merangkum secara berasingan kaedah pengebilan pemprosesan dan pengiraan output ke dalam kelas strategi pengebilan.

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

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 : 一次课结算;
Salin selepas log masuk
Delegasi gabungan
Warisan ialah hubungan bapa-anak.

3 Hasilkan objek

3.1 Corak Singleton Pastikan hanya terdapat satu kes penggunaan dalam sistem Contohnya, fail konfigurasi sistem.

Isi penting

1: Pembina adalah peribadi.

2: Kelas itu sendiri mengandungi sifat instantiasinya sendiri.

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

3.2 Mod Kilang
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();
Salin selepas log masuk
Gunakan satu kelas induk untuk menghasilkan berbilang subkelas dengan fungsi yang berbeza.

Ciri: Surat-menyurat satu dengan satu antara bahagian produk (Sina Weibo) dan bahagian permintaan (memaparkan Sina Weibo).

Masalah: Dalam Evernote, sumbernya mungkin Sina Weibo atau Pembangun Toutiao Apabila Evernote dipaparkan, pengepala dan pengaki kedua-duanya adalah berbeza.

3.3 Corak AbstrakKemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

RLGL!!!. Evernote bukan sahaja perlu memaparkan kandungan Sina Weibo!!! Ia juga perlu memaparkan akaun Sina dan Weibo saya~ Jangan risau, cium saya.

Model kilang digunakan terutamanya untuk menghasilkan surat-menyurat satu-dengan-satu antara bahagian produk dan bahagian permintaan, manakala mod abstrak bertujuan untuk menjadi bahagian permintaan (Evernote_display Sina Weibo), yang memerlukan beberapa kilang (menghilangkan permintaan berpihak kepada berbilang pihak permintaan), seperti kilang yang menyediakan kandungan Sina, kilang yang menyediakan akaun Sina, kilang yang memberikan ulasan pada kandungan Weibo, dll.

Kod:Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

3.4 平行模式

当使用工厂/Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam必须要制定具体的创建者(需求方).

平行模式和Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam的模型图一致,但代码实现不一样.

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam中父类均为抽象类,而平行模式中,所以类都为普通类,方便父类的实例化.

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

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;
Salin selepas log masuk

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

4 使用对象
4.1 Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam,可以理解为单一对象管理组合对象(聚合组件),最终组合体下的各个组合部件最好类型一致.不然特殊性越多,需要判断就越多.

假设捶背男,洗脚男,洗发男,用来服务一个人(妹子).

假设妹子的几个部位可用的服务男均为无限个.

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

//创建一个妹子
$妹子 = new 人();

//添加洗脚男、捶背男
$妹子->add_man(new 洗脚男);
$妹子->add_man(new 捶背男);

//循环所有男的给予舒服的方法.
$妹子->计算舒服程度();
Salin selepas log masuk

这是一个很理想的Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam,在现实情况,我们使用Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam,可能不得不创建多种类型的洗脚男,需要添加许多判断条件.

4.2 Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam,首先洗脚男,洗发男,捶背男都是人,但是如果,一个男的又捶背,又洗发,这怎么玩?.add_man两次?这不科学吧,来给这些男的装饰一下吧~

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

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,注意顺序,由里到外执行.
Salin selepas log masuk

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam,既(组合+继承),基类方法一定要尽量少,不然子类可能有它不该有的方法.直接类继承,她只可能是一种形态,而她的多种形态可能一并拥有的时候,应该运用组合.

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

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

这只是确保不可能出现在男,女之外的第三种人,如果基类为动物,给予服务的可能是鸡,鹅,鸭,那么装饰类型应该运用Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam,动物形态和装饰形态一一对应.方便拓展.

除了服务类型,服务男的样子也很重要,这就多了一种装饰,现在有装饰男类型和相貌男类型,这种情况怎么破,其实类似.Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

复制代码 代码如下:

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

4.3 外观模式

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

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

5 执行任务
5.1 策略模式

给类添加功能.对象要显式的调用它.

继续刚才的洗脚男和人的故事吧...你丫的爽完了要给钱吧?支付宝?微信?现金?

这个付款方式有多种,实现方法不应该放在人类中,而是应该委托给别的类

abstract class 人 {

  protectd $支付方式;

  function set_支付方式(){...}

  function 付款(金额){
    return $支付方式->付款($金额);
  }
}

abstract class 付款{
  abstract function 付款($金额);
}

class 支付宝付款 extends 付款{

  function 付款($金额){
    return 外接支付宝付款流程($金额);
  }
}
...

//使用
$男 =new 男();

///爽爽爽
...

//结账
$支付宝支付账单 = new 支付宝付款($金额);
$人 = new 男();
$人->set_支付方式(new 支付宝付款());
$人->付款();
Salin selepas log masuk

5.2 Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

当被观察者发生变化,观察者需要被通知.

当数据发生变化,页面需要被通知.

使用步骤:

观察者加载到被观察者中.
被观察者通知观察者.

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

例如登陆类(被观察)状态改变,要出发邮件系统和日志系统(观察者)

interface 被观察者{
  function attach(观察者);
  function detatch(观察者);
  function notify();
}

class Login implements 被观察者{
  private $观察者;

  function __construct(){
    $this->观察者 = array();
  }

  function attach($观察者){
    $this->观察者 = $观察者; 
  }

  function detach($观察者){
    //删除某个观察者的操作;
  }

  function notify(){
    foreach ($this->观察者 as $单个观察者){
      $单个观察者->update($this);
    }
  }    
}

interface 观察者{
  function update(被观察者);
}

abstract class Login_观察者 implements 观察者{
  private $login;
  function __construct (Login $login){
    $this->login = $login;
    $login->attach($this);
  }

  function update(观察者 $观察者){
    if ($观察者 ===$this->login){
      $this->do_update($观察者);
    }
  }
  abstract function do_update(Login $login);
}

class 邮件观察者 extends 登陆观察者 {
  function do_update(Login $login){
    //判断条件 发送邮件
  }
}


class 日志观察者 extends 登陆观察者 {
  function do_update(Login $login){
    //判断条件 记录到日志;
  }
}

//使用
$login = new Login();
new 邮件观察者 ($login);
new 日志观察者 ($login);
Salin selepas log masuk

PHP有内置的SPL实现上述的Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam.

5.3 Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

问题: 在一个军队中,有很多军队,军队下面可能包含军队/步兵/弓箭手,这时我们要显示一个军队的战斗力/需要粮食的各级分配?(遍历对象并设置显示方法).怎么办?.解决办法是军队还是保存自己的基本信息,设置一个访问者,访问者包含总战斗力方法和总粮食的方法.

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

访问者

abstract class 军队访问者{
  abstract function 访问(单元);

  function 访问军队($军队){
     $this->访问($军队);
  }
  function 访问弓箭手($弓箭手){
    $this->访问($弓箭手);
  }

  //这里重复定义了大量代码,其实可以用call来替代
  function __call($method_name,$args){
    if(strrpos($method_name, "访问")){
      return call_user_func_array(
        array($this,"访问"),$args
      );
    }
  }
}

class 军队战斗力访问者 extends 军队访问者{
  private $text="";

  function 访问($单元){
    $ret = "";
    $pad = 4*$单元->getDpth(); //设置显示深一级前面多4个空格.
    $ret .= sprintf( "%{$pad}s","");
    $ret .= get_class($单元). ": ";
    $ret .= "战斗力: " .$单元->bombardStrenth()."\n";
    $this->text .=$ret;
  }

  function get_text(){
    return $this->text;
  }
}
Salin selepas log masuk

被访问者

abstract class 单元{
  function 接受($军队访问者){
    $method = "访问_".get_class($this);
    $军队访问者->$method($this);
  }

  private $depth;
  protected function set_depath($depth){
    $this->depth=$depth;
  }

  function get_depth(){
    return $this->depth;
  }
  ...
}

abstract class 综合单元 extends 单元{
  function 接受($军队访问者){
    parent::接受($军队访问者)
    foreach($this->单元集合 as $this_unit){
      $this->unit->接受($军队访问者);
    }
  }
}

class 军队 extends 综合单元{
  function bombardStrenth(){
    $ret =0;
    foreach($this-units() as $unit){
      $ret += $unit->bombardStrenth();
    }
    return $ret
  }
}

class 弓箭手 extends 单元{
  function bombardStrenth(){
    return 4;
  }
}
Salin selepas log masuk

调用

$main_army = new Army();
$main_army->add_unit(new 步兵());
$main_army->add_unit(new 弓箭手());

$军队战斗力访问者_实例 =new 军队战斗力访问者();
$main_army->接受(均分战斗力访问者);
print $军队战斗力访问者->get_text();
Salin selepas log masuk

输出

复制代码 代码如下:

军队: 战斗力: 50
步兵: 攻击力 :48
弓箭手: 攻击力: 4

5.4 Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

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

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

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

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam比较适合命令执行例如登陆,反馈等简单只需要判断是否成功的任务

Kemahiran PHP berorientasikan objek, corak dan amalan_javascript yang mendalam

命令:

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;
  }
}
Salin selepas log masuk

部署命令的调用者

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

}
Salin selepas log masuk

客户端

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{
      //成功 分发视图
    }
  }
}
Salin selepas log masuk

使用

$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();
Salin selepas log masuk

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan