PHP面试 PHP基础知识 九(面向对象)

面向对象

  PHP的类权限控制修饰符

    public(公共的) 、 protected(受保护的)、private(私有的)

    public :最高权限   可以在类的内部使用  可以在类的外部使用  可以在子类中使用

    protected:可以在类的内部使用   可以在子类当中使用

    private:只能在类的内部使用   不可以被继承  不可以在类的外部使用

  面向对象的封装、继承、多态

    封装:成员访问权限   public  protected  private 访问权限问题

    继承:单一继承    同时只能继承一个类

        方法重写  子类继承一个父类   在子类中写一个于父类相同的方法名会把父类的方法覆盖掉

       如果不想覆盖可以使用parent先调用一下父类的方法

class  Father{
      public function test(){
       }  
}        

class Son extends Father{
      public function test(){
         
          parent::test();
           
           .....
      }
}    

     多态:

      抽象类的定义

抽象类定义前面以abstract关键字开始  
类中可以定义多个方法,可以具体实现方法,也可定义抽象方法,抽象方法就是没有绝体实现的方法,需要在方法前加 abstract 关键字,抽象方法需要在子类中实现
类中只要有抽象方法,这个类必须定义为抽象类。
抽象类和接口一样不能直接实例化为对象,只能被普通类继承。

定义一个抽象类
abstract class MyList{
       
       //抽象方法需要在子类中实现
       abstract  public function  selectgroup($where);

       public function del($where){

            echo  "删除成功";

       }
}

//Tag类继承MyList抽象类
class  Tag extends MyList{
        //实现抽象方法
        public   function selectgroup(){
         
             echo "查找数据";

       }

} 

//Plist类继承MyList抽象类
class Plist extends MyList{
        //实现抽象方法
        public  function selectgroup(){
        
               echo  "查找数据库";      
  
        }

}

      接口的定义    interface 声明定义接口     一句话说明:类方法必须实现,接口的方法必须为空

        不同类的共同方法在接口中定义,然后在不同类中实现不同的功能

        接口本身就是抽象的不用加  abstract

        一个类可以一次实现多个接口   语法用implements实现

        接口可以被继承 用extends

        接口定义方法只能使用public

        接口不能创建自己的对象   

interface Action(){
       
       public function eat($foods);  

}



//普通类实现接口方法

calss Human implements Action(){
    
       //实现接口必须提供接口中的方法
   
       public  function eat($foods){
      
              echo "Human eat";
       }
    
}    

class  Animal implements Action(){ 

          public function eat( $foods){ 

              echo "Animal eat {$foods}"; 
          
           }

}

//调用完成的方法
$human = new Human(); 

$human->eat(); 

 
$animal = new Animal(); 

$animal->eat(); 


///   instanceof 判断某个对象是否实现了某个接口

function CheckEat( $obj ){ 

    if(     $obj instanceof Action  ){ 

        $obj->eat(  'orange' ); 

    }else{ 

        echo "the object not implements Action"; 

    } 

} 

CheckEat( $human ); 

CheckEat( $animal );


//接口继承

//extends 让接口继承接口 

interface IcanPee  extends Action(){ 

   public function pee(); 

} 

 

//当类实现子接口时,父接口定义的方法也需要在这个类里面具体实现 

Class Human1 implements IcanPee(){ 

   public function pee(){  } 

   public function eat( $foods ){  } 

} 
  魔术方法

  __construct()    构建对象时使用

  __destruct()      明确销毁对象或脚本结束时被调用

  __call()              调用不可访问或不存的方法时被调用

   __callStatic()    调用不可访问或不存在的静态方法时被调用

  __get()               读取不可访问或不存在的属性时被调用

  __set()                当给不可访问或不存在的属性赋值时被调用

  __isset()              对不可访问或不存在的属性调用isset()或empty()时被调用

  __unset()             对不可访问或不存在的属性进行unset时被调用

  __sleep()             当使用serialize时被调用,当你不需要保存大对象的所有数据时很有用

  __wakeup()          当使用unserialize时被调用,可用于做些对象的初始化操作

  __toString()          当一个类被转换成字符串时被调用

  __clone()              进行对象clone时被调用   用来调整对象的克隆行为

  __invoke()             当以函数方式调用对象时被调用

    __set_state()          当调用var_export()导出类时,此静态方法被调用。用__set_state的返回值做为var_export的返回值

  __debuginfo()        当调用var_dump()打印对象时被调用(不想打印所有属性)PHP5.6版本

class MyExample{
      
      public $var = 'test';
      
     //构造函数
      public   function   __construct()
      {
            echo  '__contruct'.PHP_EOL;
      }
     
     //对象的引用都被删除、对象被销毁、调用exit()后、脚本关闭时被调用
  public   function   __destruct()
      {
            echo '__destruct'.PHP_EOL;
      }
     
     //调用不可访问或不存在的方法时被调用
  public   function  __call($name, $arguments)
      {
            echo '__call'.PHP_EOL;
      } 
      
      //调用不可访问或不存在的静态方法时被调用
  public  static  function  __callStatic($name, $arguments)
     {
              echo '__callStatic'.PHP_EOL;
     }

     //读取不可访问或不存在的属性时被调用
  public  function  __get($name)
     {
              echo '__get'.PHP_EOL;
     }
     
     //不可访问或不存在的属性赋值时调用
      public   function   __set($name, $value)
      {
              echo '__set'.PHP_EOL;
      }

      //不可访问或不存在的属性调用isset()或empty()时被调用
  public  function   __isset($name)
      {
              echo '__isset'.PHP_EOL;
      }
      
      //不可访问或不存在的属性unset时被调用
  public   function  __unset($name)
     {
              echo '__unset'.PHP_EOL;
      }

      //serialize时被调用 ,不需要保存大对象的所有数据时有用
  public   function   __sleep()
     {
           echo '__sleep'.PHP_EOL;
           return array('var111111111111111');
     }

      //unserialize时被调用,可用于做些对象的初始化操作
  public   function  __wakeup()
     {
            echo '__wakeup'.PHP_EOL;
            $this->var = 'test after wakeup';
     }

     //一个类被转换为字符串时被调用
  public   function __toString()
     {
             return '__toString'.PHP_EOL;
     }

     //进行对象clone时被调用   用来调整对象的克隆行为
  public   function  __clone()
     {
            echo '__clone'.PHP_EOL;
     }
     
     //以函数方式调用对象时被调用
     public  function  __invoke()
     {
             echo '__invoke'.PHP_EOL;
     }

     //当调用var_export()导出类时,此静态方法被调用。用__set_state的返回值做为var_export的返回值。
     public  static  function __set_state($arr)
    {
            return  '__set_state'.PHP_EOL;
    }
    
    //调用var_dump()打印对象时被调用(当你不想打印所有属性)适用于PHP5.6版本
    public function __debuginfo()
    {
            echo '__debuginfo'.PHP_EOL;
            return array(
                           'var' =>'test fro __debuginfo'
                       );
    }

}  

$m = new MyExample();        //__construct()被调用
$m->not_exist_property = test;    //__set()被调用
echo $m->not_exist_property;    //__get()被调用
$m->abc(1,2,3);       //__call()被调用
echo isset($m->not_exist_property);   //__isset()被调用,返回bool值
unset($m->not_exist_property); //__unset()被调用
echo $tmp = serialize($m); //__sleep()被调用
unserialize($tmp); //__wakeup()被调用
$m1 = clone $m; //__clone()被调用,对象默认是引用传递,使用clone关键词则可实现对象复制
$m();     //__invoke()
eval( '$m2 = '  .  var_export ( $m ,  true ) .  ';');var_dump($m2);
var_dump($m);
//最后__destruct()被调用
  设计模式

    常见的设计模式:工厂模式、单例模式、注册树模式、适配器模式、观察者模式、策略模式

  工厂模式

    工厂模式是最常用的实例化对象模式,使用工厂方法代替new操作的一种模式

    工厂模式的好处是,你想要更改所实例化的类名等,则只需要更改工厂方法内容即可,不需逐一寻找代码中具体实例化的地方修改。为系统结构提供了灵活的动态扩展机制,减少耦合。

/**
 *简单工厂模式(静态工厂方法模式)
 */
/**
 * Interface people 人类
 */
interface  people
{
    public function  say();
}
/**
 * Class man 继承people的男人类
 */
class man implements people
{
    // 具体实现people的say方法
    public function say()
    {
        echo '我是男人<br>';
    }
}
/**
 * Class women 继承people的女人类
 */
class women implements people
{
    // 具体实现people的say方法
    public function say()
    {
        echo '我是女人<br>';
    }
}
/**
 * Class SimpleFactoty 工厂类
 */
class SimpleFactoty
{
    // 简单工厂里的静态方法-用于创建男人对象
    static function createMan()
    {
        return new man();
    }
    // 简单工厂里的静态方法-用于创建女人对象
    static function createWomen()
    {
        return new women();
    }
}
/**
 * 具体调用
 */
$man = SimpleFactoty::createMan();
$man->say();
$woman = SimpleFactoty::createWomen();
$woman->say();
  单例模式

    单例模式确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

    单例模式一种常见的设计模式。比如用于,线程池、缓存、日志对象、对话框、打印机、数据库操作等。

    单例模式分为三种:懒汉式单例、饿汉式单例、登记式单例。

    有三个特点:

      1、只能有一个实例。

      2、必须自行创建这个实例

      3、必须给其他对象提供这一实例

    为什么要使用单例模式?

    PHP一个主要应用场合就是引用程序和数据库打交道的场景,在一个应用中会存在大量的数据库操作,针对数据库连接数据库行为,使用单例模式可以避免大量的new操作。因为每一次new操作都会消耗和内存的资源。

class Single {
    private $name;//声明一个私有的实例变量
    private function __construct(){//声明私有构造方法为了防止外部代码使用new来创建对象。
    }
    static public $instance;//声明一个静态变量(保存在类中唯一的一个实例)
        static public function getinstance(){//声明一个getinstance()静态方法,用于检测是否有实例对象
        if(!self::$instance) self::$instance = new self();
            return self::$instance;
    }
    public function setname($n){ $this->name = $n; }
        public function getname(){ return $this->name; }
}
$oa = Single::getinstance();
$ob = Single::getinstance();
$oa->setname('hello world');
$ob->setname('good morning');
echo $oa->getname();//good morning
echo $ob->getname();//good morning
  注册模式

    注册模式,解决全局共享和交换对象。已经创建好的对象,挂在某个全局可以是哟个的数组上,在需要使用的时候,直接从该数组上获取即可。将对象注册到全局树上,任何地方直接去访问。

class Register
{
    protected static  $objects;
        function set($alias,$object)//将对象注册到全局的树上
        {
            self::$objects[$alias]=$object;//将对象放到树上
        }
        static function get($name){
        return self::$objects[$name];//获取某个注册到树上的对象
    }
    function _unset($alias)
  {
        unset(self::$objects[$alias]);//移除某个注册到树上的对象。
    }
}
  适配器模式

    将各种截然不同的函数接口封装成统一的API

    PHP中的数据库操作有MySQL、MySQLi、PDO三种,可以使用适配器模式统一成一致,使不同的数据库操作,统一成一样的API。类似的场景还有cache适配器,可以将memcache,redis,file,apc等不同的缓存函数,统一成一致。

    首先定义一个接口(有几个方法,以及相应的参数)。然后,有几种不同的情况,就写几个类实现该接口。将完成相似功能的函数,统一成一致的方法。

//接口  IDatanase
interface IDatabase
{
    function connect($host, $user, $passwd, $dbname);
    function query($sql);
    function close();
}

//   Mysql
class MySQL implements IDatabase
{
    protected $conn;
        function connect($host, $user, $passwd, $dbname)
        {
            $conn = mysql_connect($host, $user, $passwd);
            mysql_select_db($dbname, $conn);
            $this->conn = $conn;
    }
    function query($sql)
        {
            $res = mysql_query($sql, $this->conn);
            return $res;
    }
    function close()
    {
        mysql_close($this->conn);
    }
}

//Mysqli
class MySQLi implements IDatabase
{
    protected $conn;
    function connect($host, $user, $passwd, $dbname)
    {
        $conn = mysqli_connect($host, $user, $passwd, $dbname);
        $this->conn = $conn;
    }
    function query($sql)
    {
        return mysqli_query($this->conn, $sql);
    }
    function close()
    {
        mysqli_close($this->conn);
    }
}
  观察者模式

  1、观察者模式,当一个对象状态发生变化时,依赖它的对象全部会收到通知,并自动更新。

  2、场景:一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理的逻辑。当更新的逻辑增多之后,代码会变的那一维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件的主体代码。

  3、观察者模式实现了低耦合,非侵入式的通知与更新机制。

// 主题接口
interface Subject{
    public function register(Observer $observer);
    public function notify();
}

// 观察者接口
interface Observer{
    public function watch();
}

// 主题
class Action implements Subject{
     public $_observers=array();
     public function register(Observer $observer){
         $this->_observers[]=$observer;
     }

     public function notify(){
         foreach ($this->_observers as $observer) {
             $observer->watch();
         }

     }
 }

// 观察者
class Cat implements Observer{
     public function watch(){
         echo "Cat watches TV<hr/>";
     }
 } 
 class Dog implements Observer{
     public function watch(){
         echo "Dog watches TV<hr/>";
     }
 } 
 class People implements Observer{
     public function watch(){
         echo "People watches TV<hr/>";
     }
 }



// 应用实例
$action=new Action();
$action->register(new Cat());
$action->register(new People());
$action->register(new Dog());
$action->notify();
  策略模式

  策略模式是对象的行为模式,用意是对一组算法的封装。动态的选择徐太的算法并使用。

  策略模式指的是程序中涉及决策控制的一种模式。策略模式功能非常强大,因为这个模式本身的核心思想就是面向对象编程的多形性思想

  策略模式三个角色

     1:抽象策略角色

     2:具体策略角色

     3:环境角色(对抽象策略角色的引用)

  实现步骤:

     1:定义抽象角色类   (定义好各个实现的共同抽象方法)

     2:定义具体策略类     (具体实现父类的共同方法)

     3:定义环境角色类     (私有化申明抽象角色变量,重载构造方法,执行抽象方法)

  打个比方说明策略模式:

     如果我需要买衣服了,我可以有几种方式买衣服?

      1、我可以在京东购买。

      2、我可以在淘宝购买。

      3、我可以找代购买。

      4、我可以去商场买。

      每个方式我都可以买到衣服,但是使用了不同方式。

    abstract class baseAgent { //抽象策略类
        abstract function PrintPage();
    }
    //用于客户端是IE时调用的类(环境角色)
    class ieAgent extends baseAgent {
        function PrintPage() {
            return 'IE';
        }
    }
    //用于客户端不是IE时调用的类(环境角色)
    class otherAgent extends baseAgent {
        function PrintPage() {
            return 'not IE';
        }
    }
    class Browser { //具体策略角色
        public function call($object) {
                return $object->PrintPage ();
            }
        }
        $bro = new Browser ();
    echo $bro->call ( new ieAgent () );

 

posted @ 2019-06-20 16:53  进化史  阅读(435)  评论(0编辑  收藏  举报