您的位置 首页 php

常见面试问题之-设计模式 重要包含PHP代码实现额,PHP开发者必看

1. PHP面向对象的高级特性-命名空间

(PHP 5 >= 5.3.0, PHP 7)

什么是命名空间?从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。

具体举个例子,文件 foo.txt 可以同时在目录/home/greg 和 /home/other 中间存在,但在同一个目录中不能存在两个 foo.txt 文件。另外,该目录 /home/greg 外访问 foo.txt 文件时,我们必须将目录名以及目录分隔符放在文件名之前得到 /home/greg/foo.txt。这个原理应用到程序设计领域就是命名空间的概念。

在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题:

  • 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
  • 为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。

PHP 命名空间提供了一种将相关的类、函数和常量组合到一起的途径。下面是一个说明 PHP 命名空间语法的示例:

 <?php
namespace my\name; // 参考 "定义命名空间" 
class MyClass {}
function myfunction() {}
const MYCONST = 1;

$a = new MyClass;
$c = new \my\name\MyClass; // 参考 "全局空间" 

$a = strlen('hi'); // 参考 "使用命名空间:后备全局函数/常量" 
$d = namespace\MYCONST; // 参考 "namespace操作符和__NAMESPACE__常量” 

$d = __NAMESPACE__ . '\MYCONST';
echo constant($d); // 参考 "命名空间和动态语言特征" 
?>  

2. 类的自动载入

require ,inclue 方便当类删除的时候,避免致命错误!

spl_autoload_register() – 注册给定的函数作为 __autoload 的实现

 class Test1{
  static  function test(){
        echo __FILE__;
    }
}
spl_autoload_register(function ($class){
    require __DIR__.'/'.$class.'.php';
});


Test1::test();  

3.PSR-0规范

  • 命名空间必须与绝对路径一致
  • 类名首字母必须大写
  • 除了入口文件外,其他‘.php’ 必须只有一个类

4.SPL标准库

 //php 栈 先进后出
$stack = new SplStack();
$stack->push('1');
$stack->push('2');

echo $stack->pop();
echo $stack->pop();

//php 队列 先进先出
$queque= new SplQueue();
$queque->enqueue('1');
$queque->enqueue('2');

echo $queque->dequeue();
echo $queque->dequeue();
//php 堆 先进先出
$heap= new SplMinHeap();
$heap->insert('1');
$heap->insert('2');

echo $heap->extract();
echo $heap->extract();  

5.魔术方法的使用,链式操作

 //链式操作
$db = new Spring\Database;
$db->where(['eq'=>1])->limit(['1'])->order(['id'=>'asc']);
方法体里面直接return $this;
function where($where)
{
  print_r($where);
  return $this;
}
$obj->title = 'aaa';// function __set(){}  function __get(){} 不存在的时候会调用的方法
$obj->test('adsa',111); function __call(){}
echo $obj();            function __toString();  

6.三种基础模式(常见的三种)

  • 工厂模式-工厂方法或者类生成对象,而不是在代码中直接new
  • 单例模式-使某个类的对象只允许创建一次
  • 注册树模式-全局共享和交换对象

6.1 工厂模式

  • -工厂方法或者类生成对象,而不是在代码中直接new
 <?php
/**
* 工厂模式
*/namespace Spring;

class Factory
{
    // 多个地方同时实例化的时候,当有参数变化的时候,方便修改
    static function createDatabase()
    {
        $db = new Database();
        return $db;
    }
}
//调用  不用实列话
\Spring\Factory::createDatabase();  

6.2 单例模式

  • -使某个类的对象只允许创建一次,避免资源浪费
 private static $instance;

//private 不能直接new
private function __construct()
{
}

static function getInstance()
{
    if (!(self::$instance instanceof self)) {
        self::$instance = new self();
    }
    return self::$instance;
}
//调用
\Spring\Database::getInstance()  

6.3 注册树模式

  • -全局共享和交换对象,可以用来被任何地方访问
 <?php
/**
* 注册树模式
*/namespace Spring;
class Register
{
    protected static $array;
    static function set($key, $value)
    {
        self::$array[$key] = $value;
    }

    static function get($key)
    {
        return self::$array[$key];
    }

    function _unset($key)
    {
        unset(self::$array[$key]);
    }
}
//注册 数据库全局信息 可以在任何地方使用
Register::set('database', $db);
//调用
\Spring\Register::get('database')  

6.4 适配器模式

  • -可以将截然不同的函数接口封装成统一的API
  • 如 mysql/mysqli/pdo ,redis/memcache 实现统一接口定义的方法
 <?php

namespace Spring\Db;

use \Spring\IDatabase;

class MySQLi implements IDatabase
{

    function connect($host, $user, $pwd, $dbname)
    {
        // TODO: Implement connect() method.
    }

    function query($sql)
    {
        // TODO: Implement query() method.
    }

    function close()
    {
        // TODO: Implement close() method.
    }
}


<?php

namespace Spring\Db;
use \Spring\IDatabase;

class MySQL implements IDatabase
{
    function connect($host, $user, $pwd, $dbname)
    {
        // TODO: Implement connect() method.
    }

    function query($sql)
    {
        // TODO: Implement query() method.
    }

    function close()
    {
        // TODO: Implement close() method.
    }
}
//调用
(new \Spring\Db\MySQL())->connect('127.0.0.1','root','root','test');  

6.5 战略模式-(面向对象经常用到的,可以实现解耦)

  • -将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,
  • 如 :一个电商网站系统,针对男性女性用户跳转到不同的商品分类,展示不同的广告 ,如果新增 一种 类型,不用写很多的if else ,互不影响 只需增加一种策略即可,实现接口,依赖关系实现反转(面向对象经常用到的,可以实现解耦)
 // 传统模式
if (isset($_GET['female'])) {

 $feMaleUserStrategy = new \Spring\FeMaleUserStrategy();
 $feMaleUserStrategy->showAd();

} else {

 $maleUserStrategy = new \Spring\MaleUserStrategy();

 $maleUserStrategy->showAd();

}

// 策略模式
interface UserStrategy
{
 function showAd();
}

class MaleStrategy implements UserStrategy{

 function showAd(){
   echo '男人';
 }
}
class FeMaleStrategy implements UserStrategy{

 function showAd(){
 echo '女人';
 }
}
class IndexController

{
 protected $strategy;
 function index(){
    $this->strategy->showAd();
}
 function setStrategy(\Spring\UserStrategy $strategy) {
    $this->strategy = $strategy;
 }
}
$index = new IndexController();
if (isset($_GET['female'])) {
 $strategy = new \Spring\FeMaleUserStrategy();
} else {
 $strategy = new \Spring\MaleUserStrategy();
}
$index->setStrategy($strategy);

$index->index();  

6.6 数据对象映射模式

  • 将对象和数据存储映射起来,对一个对象的操作会银蛇为对数据存储的操作
  • 例:实现ORM类,将复杂的SQL语句映射成对象的属性操作
  • 结合 工厂模式,注册树模式以及数据对象映射模式(可以屏蔽数据库底层调用)
 /运用 工厂模式 注册树模式 和 数据对象映射模式

public function test1(){

 //不通过 new 方式 创建 user 对象 ,而是通过 工厂模式, 静态调用 createUser ,user 对象通过注册树模式 注册 ,防止重复实列化

 $user = \Spring\Factory::createUser(2);

 $user->name = 1;

 $this->test2();

 var_dump($user);

}
public function test2(){

 $user = \Spring\Factory::createUser(1);

 $user->name = 2;
 var_dump($user);
}
  

6.7 观察者模式

  • 当一个对象状态发生变化时,他的对象会全部收到通知,并自动更新
  • 例子:一个事件发生后一连串更新操作,传统的方式就是在代码 加逻辑,逻辑增多 难以维护,这种方式是耦合的,增加新的逻辑需要修改事件主体的代码 ,
  • 它实现了低耦合,非侵入式的通知与更新机制
 //基础事件
class Event extends \Spring\EventGenerator{
    //传统,模式
    function trigger1(){
        echo "逻辑1";
        echo "逻辑2";
        echo "逻辑3";
    }
    //观察者模式
    function trigger2(){
        //通知所有的观察者
        $this->notify();
    }
}
$event = new Event();
//观察者1
class  Observer1 implements \Spring\Observer{
    function update($eventInfo = [])
    {
        echo '逻辑1';
        // TODO: Implement deal() method.
    }
}
//观察者2
class  Observer2 implements \Spring\Observer{
    function update($eventInfo = [])
    {
        echo '逻辑2';
        // TODO: Implement deal() method.
    }
}
//实现 观察者1 处理逻辑1
$event->addObserver(new Observer1);
//实现 观察者2 处理逻辑2
$event->addObserver(new Observer2);
//通知
$event->trigger1();
$event->trigger2();

<?php
//观察者模式
namespace Spring;
abstract class EventGenerator
{
    protected $observer = [];
    //添加观察者
    function addObserver(Observer $observer)
    {
        $this->observer[] = $observer;
    }
    //通知 其他 观察者
    function notify()
    {
        foreach ($this->observer as $observer) {
            $observer->deal();
        }
    }
}
//实现接口 更新逻辑
<?php
namespace Spring;
interface Observer
{
    function deal($eventInfo = []);
}  

6.8 原型 模式

  • 与工厂模式作用类似,都是用来创建对象
  • 与工厂模式实现不同,原型模式是先创建好一个原型对象然后通过clone 原型对象来创建新的对象,这样就避免类创建时重复初始化操作。
  • 原型模式适用于大对象的创建,创建一个大对象需要很大的开销,如果每次NEW就会消耗很大,原型模式仅仅需要内存拷贝即可
 $prototype = new Canvas();
$prototype->init();

$canvas1 = clone  $prototype;
$canvas2 = clone  $prototype;
$canvas1->dosomething();
$canvas2->dosomething();  

6.9 装饰器 模式

  • 可以动态的添加,修改类的功能
  • 一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类来继承他,并重新实现类的方法。
  • 使用装饰器 模式, 仅仅需要在运行时添加一个装饰器对象即可实现,可以实现灵活性
 <?php
//装饰器模式
namespace Spring;

interface  DrawDecorator
{
    function beforeDraw();
    function afterDraw();
}

class Canvas
{
    protected $decorators = [];
    //添加装饰器
    function addDecorator(DrawDecorator $drawDecorator)
    {
        $this->decorators[] = $drawDecorator;
    }
    function beforeDraw()
    {
        foreach ($this->decorators as $decorator) {
            $decorator->beforeDraw();
        }
    }
    function afterDraw()
    {
       //控制反转不然,顺序不对
        $decorators = array_reverse($this->decorators);
        foreach ($decorators as $decorator) {
            $decorator->afterDraw();
        }
    }
    function draw()
    {
        echo "";
        $this->beforeDraw();
        echo "";
        echo '画画' . "";
        $this->afterDraw();
    }
}
class ColorDecorator implements \Spring\DrawDecorator {
    function beforeDraw()
    {
        // TODO: Implement beforeDraw() method.
        echo 'beforeDrawColor';
    }
    function afterDraw()
    {
        echo 'afterDrawColor';
        // TODO: Implement afterDraw() method.
    }
}
class SizeDecorator implements \Spring\DrawDecorator {
    function beforeDraw()
    {
        echo 'beforeDrawsize';
        // TODO: Implement beforeDraw() method.
    }
    function afterDraw()
    {
        echo 'afterDrawsize';
        // TODO: Implement afterDraw() method.
    }
}

$canvas = new \Spring\Canvas();
$canvas->addDecorator(new ColorDecorator);
$canvas->addDecorator(new SizeDecorator);
$canvas->draw();  

6.10 迭代器 模式

  • 在不需要了解内部实现的前提下遍历一个聚合对象的内部元素。
  • 相比传统的编程模式,它可以隐藏遍历元素所需的操作
 <?php
namespace Spring;


class AllUser implements \Iterator
{
    protected $ids;
    protected $data = array();
    protected $index;
    function __construct()
    {
        $db = Factory::createDatabase();
        $result = $db->query("select id from user");
        $this->ids = $result->fetch_all(MYSQLI_ASSOC);
    }
    function current()
    {
        $id = $this->ids[$this->index]['id'];
        return Factory::getUser($id);
    }
    function next()
    {
        $this->index ++;
    }
    function valid()
    {
        return $this->index < count($this->ids);
    }
    function rewind()
    {
        $this->index = 0;
    }
    function key()
    {
        return $this->index;
    }
}  

6.11代理模式

在客户端与实体置渐建立一个代理对象proxy 客户端对实体进行操作全部委派给代理对象,隐藏实体的具体实现细节

 <?php
namespace Spring;
class Proxy implements IUserProxy
{
    function getUserName($id)
    {
        $db = Factory::getDatabase('slave');
        $db->query("select name from user where id =$id limit 1");
    }
    function setUserName($id, $name)
    {
        $db = Factory::getDatabase('master');
        $db->query("update user set name = $name where id =$id limit 1");
    }
}
$proxy = new Proxy();
$proxy->getUserName(1);
$proxy->setUserName(1,1);  

7 面向对象编程的基本原则

  • 单一职责:一个类,只需要做好一件事情。
  • 开放封闭:一个类,应该是可扩展的。而不可修改的
  • 依赖倒置:一个类,不应该强依赖另一个类。每一个类对于另一个类都是可替换的。
  • 配置话:尽可能地使用配置,而不是硬编码
  • 面向接口编程:只需要关心接口,不需要关心实现

7.1 MVC结构

模型-试图-控制器,一种C/S或者B/S软件工程的组织方式

  • 模型(model):数据和存储的封装
  • 视图(view):展示层的封装
  • 控制器(controller):逻辑层的封装

7.2 配置与设计模式

  • 在工厂方法中读取配置,生成可配置化的对象
  • 使用装饰器模式实现权限验证,模板渲染,json串化
  • 使用观察者模式实现数据更新事件的一系列更新操作
  • 使用代理模式实现数据库的主从自动切换

话说要经常看美女才会活得久。

结束语:编码不易,谢谢你这么好看,还关注我,记得点赞额!您的支持是我写下去的动力!

文章来源:智云一二三科技

文章标题:常见面试问题之-设计模式 重要包含PHP代码实现额,PHP开发者必看

文章地址:https://www.zhihuclub.com/79034.shtml

关于作者: 智云科技

热门文章

网站地图