• 3.25周 一周拾遗


    PHP设计模式

    自动加载

    __autoload();

    魔术方法,当加载不存在的类的时候会使用这个方法,每个文件中只能存在一次,而且抛出的Exception是不可catch的。

    spl_autoload_register();

    可以调用用户自己的ClassLoader, Composer就是使用这种方法实现类的自动加载

    每个文件中可有多个spl_autoload_register();方法,调用更加灵活;

    抛出的Exception可以catch;

    而且可以使用 spl_autoload_unregister();进行自动加载关闭,节省内存空间.

    • 自动加载不可用于CLI模式

    PSR-0规范

    PSR-0 (Autoloading Standard) 自动加载标准

    PSR-1 (Basic Coding Standard) 基础编码标准

    PSR-2 (Coding Style Guide) 编码风格向导

    PSR-3 (Logger Interface) 日志接口

    PSR-4 (Improved Autoloading) 自动加载的增强版,可以替换掉PSR-0了。

    一个完全合格的namespace和class必须符合这样的结构:“< Vendor Name>(< Namespace>)*< Class Name>”

    每个namespace必须有一个顶层的namespace(”Vendor Name”提供者名字)

    每个namespace可以有多个子namespace

    当从文件系统中加载时,每个namespace的分隔符(/)要转换成 DIRECTORY_SEPARATOR(操作系统路径分隔符)

    在类名中,每个下划线(_)符号要转换成DIRECTORY_SEPARATOR(操作系统路径分隔符)。在namespace中,下划线(_)符号是没有(特殊)意义的。

    当从文件系统中载入时,合格的namespace和class一定是以 .php 结尾的

    verdor name,namespaces,class名可以由大小写字母组合而成(大小写敏感的)

    PSR-4 规范

    废除了支持PHP5.3代码以前的规范,并且去掉的下划线的意义。

    八个常用设计模式

    单例模式 Eg。数据库连接

    要求:

    1. $_instance必须为静态私有变量

    2. 构造函数 析构函数 拷贝函数必须为私有 防止外界实例化对象

    3. getInstance()方法必须公有,返回实例一个引用。

    节省内存 避免频繁new

    工厂模式:生产对象使用

    工厂模式可以避免类改名字之后,其他生成对象的代码都要一一修改,使用工厂可以避免频繁修改。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    Test1.php
    <?php
    class Test1{
    static function test(){
    echo __FILE__;
    }
    }

    Factory.php
    <?php
    class Factory{
    /*
    * 如果某个类在很多的文件中都new ClassName(),那么万一这个类的名字
    * 发生变更或者参数发生变化,如果不使用工厂模式,就需要修改每一个PHP
    * 代码,使用了工厂模式之后,只需要修改工厂类或者方法就可以了。
    */
    static function createDatabase(){
    $test = new Test1();
    return $test;
    }
    }

    Test.php
    <?php
    spl_autoload_register('autoload1');

    $test = Factory::createDatabase();
    $test->test();
    function autoload1($class){
    $dir = __DIR__;
    $requireFile = $dir."\".$class.".php";
    require $requireFile;
    }

    注册模式:解决全局局部共享对象使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?php

    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 比如数据库操作有MySQL,MySQLi,PDO。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    接口 IDatabase
    <?php
    namespace IMooc;
    interface IDatabase
    {
    function connect($host, $user, $passwd, $dbname);
    function query($sql);
    function close();
    }

    MySQL
    <?php
    namespace IMoocDatabase;
    use IMoocIDatabase;
    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
    <?php
    namespace IMoocDatabase;
    use IMoocIDatabase;
    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);
    }
    }

    策略模式:IOC思想 DI实现

    也就是控制反转 依赖注入

    防止种类过多时候发生太多if导致代码维护艰难

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    UserStrategy.php
    <?php
    /*
    * 声明策略文件的接口,约定策略包含的行为。
    */
    interface UserStrategy
    {
    function showAd();
    function showCategory();
    }


    MaleUser.php
    <?php
    require_once 'Loader.php';
    class MaleUser implements UserStrategy
    {
    function showAd(){
    echo "IPhone6s";
    }
    function showCategory(){
    echo "电子产品";
    }
    }



    Page.php//执行文件
    <?php
    require_once 'Loader.php';
    class Page
    {
    protected $strategy;
    function index(){
    echo "AD";
    $this->strategy->showAd();
    echo "<br>";
    echo "Category";
    $this->strategy->showCategory();
    echo "<br>";
    }
    function setStrategy(UserStrategy $strategy){
    $this->strategy=$strategy;
    }
    }

    $page = new Page();
    if(isset($_GET['male'])){
    $strategy = new MaleUser();
    }else {
    $strategy = new FemaleUser();
    }
    $page->setStrategy($strategy);
    $page->index();

    观察者模式

    适用于一带多频繁更新的操作,比如业务逻辑中一个数据更改导致其他表的数据也要跟着更改,直接硬编码更改的操作的不太好的,而且后期的维护也很不利,使用观察者模式可以进行事件发布,然后进行foreach进行更新操作。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    EventGenerator.php
    <?php
    require_once 'Loader.php';
    abstract class EventGenerator{
    private $observers = array();
    function addObserver(Observer $observer){
    $this->observers[]=$observer;
    }
    function notify(){
    foreach ($this->observers as $observer){
    $observer->update();
    }
    }
    }


    Observer.php
    <?php
    require_once 'Loader.php';
    interface Observer{
    function update();//这里就是在事件发生后要执行的逻辑
    }


    //一个实现了EventGenerator抽象类的类,用于具体定义某个发生的事件
    require 'Loader.php';
    class Event extends EventGenerator{
    function triger(){
    echo "Event<br>";
    }
    }
    class Observer1 implements Observer{
    function update(){
    echo "逻辑1<br>";
    }
    }
    class Observer2 implements Observer{
    function update(){
    echo "逻辑2<br>";
    }
    }
    $event = new Event();
    $event->addObserver(new Observer1());
    $event->addObserver(new Observer2());
    $event->triger();
    $event->notify();

    原型模式

    和工厂模式类似,适合创建大对象的时候,可以节约一下内存开销

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Index.php
    <?php
    require 'Loader.php';
    $c = new Canvas();
    $c->init();
    / $canvas1 = new Canvas();
    // $canvas1->init();
    $canvas1 = clone $c;//通过克隆,可以省去init()方法,这个方法循环两百次
    //去产生一个数组。当项目中需要产生很多的这样的对象时,就会new很多的对象,那样
    //是非常消耗性能的。
    $canvas1->rect(2, 2, 8, 8);
    $canvas1->draw();
    echo "-----------------------------------------<br>";
    // $canvas2 = new Canvas();
    // $canvas2->init();
    $canvas2 = clone $c;
    $canvas2->rect(1, 4, 8, 8);
    $canvas2->draw();

    MySQL 性能索引

    索引数据结构

    1. B+ Tree

    key放在叶子节点内的节点,叶子节点存放value 这样可以保证放更多的key,减少树的高度,树的高度的减少导致磁盘IO减少,可以优化性能。叶子节点处有相互链接的指针。InnoDB采用B+Tree可以将随机IO转换为顺序IO来提升效率。

    1. 搜索树

    父节点大于左孩子节点,右孩子节点大于父节点

    1. 平衡二叉树

    二叉树,但是要求任意一个节点的左右孩子节点高度差不大于1

    1. Hash Struct

    哈希结构仅能满足 Exist In 等查询,不能使用范围查询。无法进行排序查询。不支持部分索引

    聚集索引和非聚集索引

    聚集索引Primary

    InnoDB的数据文件本身就是索引文件,B+Tree的叶子节点上的data就是数据本身,key为主键,这是聚簇索引

    非聚簇索引,叶子节点上的data是主键(所以聚簇索引的key,不能过长)。

    索引的优点

    • 变随机IO为顺序IO

    • 避免全表扫描

    • 可以帮助服务器避免排序或者临时表

    索引对中小型表会比较高效,大型表需要考虑一下分区。

    索引的创建方法

    1
    2
    3
    4
    5
    6
    7
    8
    create index `idx_img` on newuser(`img`);

    alter table newuser add index `idx_extra_img` (`isDeleted`, `img`)

    drop index `idx_img` on newuser;

    // 强制走索引的方式
    select * from newuser force index where xxxx;

    索引的注意

    • 不鼓励使用like 不可以全部模糊查询 可以 55kai% 这样查

    • 不可以进行列上操作 比如count sum等都会全表扫描 性能很差

    • 不适用Not in <> 操作。

    • 尽可能使用分解关联查询 这样分解后 sql简单,利于MySQL缓存、减少锁竞争 更好的扩展和维护性。

    HTTP 超文本传输协议

    协议格式

    三部分:

    请求起始行、消息头、消息体

    分块传送

    当浏览器想服务器请求一个资源,这个资源是一个动态资源,服务器无法预知资源的大小,就应该采用分块传送

    服务器先生成一个thunk 发送这个chunk 再生成 在发送 直到发送完成。

    分块发送需要在请求头增加一个transfer-encoding:thunked

    持久链接

    HTTP早期版本因为链接不可复用,性能很差,TCP1.5的RTT(三次握手)和慢启动会拖慢速度。

    1.1版本引入keep-alive的connection头,如果服务器和客户端都确定keep-alive的话,在一个TCP上面可以传送多个请求。

    持久链接也不应该一直保持,每个人都会占用服务器资源,如果PV太高,服务器资源也会jinzhang

    应该配置KeepAliveTimeout和KeepAliveRequests两个参数 限时限量

    PipeLine管线化

    也就是一个TCP上面可以产送多个HTTP请求,但是请求的顺序必须和返回的顺序一致

    无状态性

    指的是协议层无状态性 两次请求并没有任何关系。通过会话控制可以保证访问的状态。

  • 相关阅读:
    超链接把一个值传到多个页面的方法
    jsp采用数据库连接池的方法获取数据库时间戳context.xml配置,jsp页面把时间格式化成自己需要的格式
    Myeclipse WEB工程JSP使用JNDI 数据库连接池连接Mysql数据库
    jsp页面图片显示不出来
    如何修改MyEclipse的默认编码方式
    MyEclipse8.5破解方法
    mysql创建的数据库在电脑什么位置?
    netsh winsock reset
    SQL Server(MSSQLSERVER)启动失败,提示“请求失败或服务未及时响应
    WIN7不能上网
  • 原文地址:https://www.cnblogs.com/xiaoerli520/p/9624265.html
Copyright © 2020-2023  润新知