框架內開發和設計模式

一、框架內開發

傳統php代碼向swoole框架升級php

直接使用如: think-swoole、swooletw/laravel-swoole ,面向對象編程的好處體現、很方便,QPS相對對簡單頁面有15+倍的提高。但《(網絡學習)三、秒殺系統與壓力測試》實測發現,只有2~3倍的提高,甚至更低。而原生hyperf框架測試確實很好看,此時性能差在哪裏?數據庫、apcu緩存。html

a.傳統php代碼向swoole框架升級

改造步驟:java

php編譯配置添加cli、swoole支持;swoole配置、兼容狀況參考官網。android

建立swoole-http對象,啓動監聽事件
$http = new Swoole\Http\Server("127.0.0.1", 9501); 
$http->on("request", function ($request, $response) { 
    //ROUTE操做
    $response->header("Content-Type", "text/plain"); 
    $response->end("Hello World\\n"); 
}); 
$http->start();
添加一鍵協程化配置

SwooleRuntime::enableCoroutine($flags = SWOOLE_HOOK_ALL);nginx

apcu開啓: apc.enable_cli
進程隔離: 若是須要在不一樣的 Worker 進程內共享數據,能夠用 RedisMySQL文件Swoole\TableAPCushmget等工具實現
php --ri apcu
apc.enable_cli => Disabled 默認值 > 1

[APCU運行時配置] https://www.php.net/manual/zh... 壓測提高狀況。laravel

swoole-table
$table = new Swoole\Table(1024);
$table->column('total_count', Swoole\Table::TYPE_INT);
$table->column('local_count', Swoole\Table::TYPE_INT);
$table->column('use_num', Swoole\Table::TYPE_INT);
$table->column('server_num', Swoole\Table::TYPE_INT);
$table->create();
$GLOBALS['table'] = &$table;
    ($GLOBALS['table'])->set(self::$REDIS_REMOTE_HT_KEY, [
            'redis_key' => self::$REDIS_REMOTE_HT_KEY,
            'total_count' => $num,
            'local_count' => $stock,
            'use_num' => 0,
            'server_num' => $data['server_num'],
    ]);
    $data = ($GLOBALS['table'])->get(self::$REDIS_REMOTE_HT_KEY);
使用swoole框架,逐類重構

重構項目另設監聽端口,與原項目並行使用、nginx分配權重。redis

b.接口開發:restful風格接口

阮一峯:《RESTful API 設計指南數據庫

版本控制
https://api.example.com/v1/
體現資源
https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees
HTTP動詞
GET /zoos:列出全部動物園
POST /zoos:新建一個動物園
GET /zoos/ID:獲取某個指定動物園的信息
PUT /zoos/ID:更新某個指定動物園的信息(提供該動物園的所有信息)
PATCH /zoos/ID:更新某個指定動物園的信息(提供該動物園的部分信息)
DELETE /zoos/ID:刪除某個動物園
GET /zoos/ID/animals:列出某個指定動物園的全部動物
DELETE /zoos/ID/animals/ID:刪除某個指定動物園的指定動物
過濾信息
?limit=10:指定返回記錄的數量
?offset=10:指定返回記錄的開始位置。
?page=2&per_page=100:指定第幾頁,以及每頁的記錄數。
?sortby=name&order=asc:指定返回結果按照哪一個屬性排序,以及排序順序。
?animal_type_id=1:指定篩選條件
狀態碼
200 OK - [GET]:服務器成功返回用戶請求的數據,該操做是冪等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。
202 Accepted - [*]:表示一個請求已經進入後臺排隊(異步任務)
204 NO CONTENT - [DELETE]:用戶刪除數據成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操做,該操做是冪等的。
401 Unauthorized - [*]:表示用戶沒有權限(令牌、用戶名、密碼錯誤)。
403 Forbidden - [*] 表示用戶獲得受權(與401錯誤相對),可是訪問是被禁止的。
404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操做,該操做是冪等的。
406 Not Acceptable - [GET]:用戶請求的格式不可得(好比用戶請求JSON格式,可是隻有XML格式)。
410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再獲得的。
422 Unprocesable entity - [POST/PUT/PATCH] 當建立一個對象時,發生一個驗證錯誤。
500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將沒法判斷髮出的請求是否成功。
錯誤處理、返回結果
{
    error: "Invalid API key"
}

GET /collection:返回資源對象的列表(數組)
GET /collection/resource:返回單個資源對象
POST /collection:返回新生成的資源對象
PUT /collection/resource:返回完整的資源對象
PATCH /collection/resource:返回完整的資源對象
DELETE /collection/resource:返回一個空文檔
推薦使用:OAuth 2.0、JSON通信
OAuth 2.0:
客戶端 ---- [ 鑑權端 -- 資源端 ]
Hypermedia API一種複雜風格約束

咱們從假定這些服務只公佈 __一個__ 對外發布的URI。編程

Richardson 提出的 REST 成熟度模型。該模型把 REST 服務按照成熟度劃分紅 4 個層次:ubuntu

  • 第一個層次(Level 0)的 Web 服務只是使用 HTTP 做爲傳輸方式,實際上只是遠程方法調用(RPC)的一種具體形式。SOAP 和 XML-RPC 都屬於此類。* 第二個層次(Level 1)的 Web 服務引入了資源的概念。每一個資源有對應的標識符和表達。
  • 第三個層次(Level 2)的 Web 服務使用不一樣的 HTTP 方法來進行不一樣的操做,而且使用 HTTP 狀態碼來表示不一樣的結果。如 HTTP GET 方法來獲取資源,HTTP DELETE 方法來刪除資源。
  • 第四個層次(Level 3)的 Web 服務使用 HATEOAS。在資源的表達中包含了連接信息。客戶端能夠根據連接來發現能夠執行的動做。

c.接口開發:RPC遠程過程調用

客戶端 ---- [ 服務端rpc.client -- 計算端rpc.server >> consul服務排隊管理 ]

二、設計模式

菜鳥教程 > 設計模式及示例(Java)

設計模式(Design pattern)表明了最佳的實踐,一般被有經驗的面向對象的軟件開發人員所採用。設計模式是軟件開發人員在軟件開發過程當中面臨的通常問題的解決方案。這些解決方案是衆多軟件開發人員通過至關長的一段時間的試驗和錯誤總結出來的。

PHP完整實戰23種設計模式

a.建立型模式旨在將系統與它的對象建立、結合、表示的方式分離,加強對象和類之間的獨立性

1) [工廠模式] 使用通用的接口類:封裝類中變化的方法,實現放到子類實現;
2) [抽象工廠模式] 組合`工廠`接口類,手動選擇工廠類;
3) [單例模式] 防止拷貝:對象引用賦值時,禁用拷貝:覆蓋__clone、另寫getInstance方法;
4) [建造者模式**]:建造者模式(Builder Pattern)
5) [原型模式] 淺拷貝|寫複製對象;

建造者模式(Builder Pattern)實例

意圖:將一個複雜的構建與其表示相分離,使得一樣的構建過程能夠建立不一樣的表示。

一、定義複雜[多級組合]父級產品類、構造類: all-in-one[1-Product產品&ProductBuilder產品構建器],接口ProductInterface、Hardware、Software,
<?php
namespace builder;
use builder\Hardware;
use builder\Software;
/**
 * 產品類
 */
class Product
{
  /**
   * 名稱
   * @var string
   */
  private $name = '';

  /**
   * 硬件
   * @var array
   */
  private $hardwares = array();

  /**
   * 軟件
   * @var array
   */
  private $softwares = array();

  /**
   * 構造函數
   *
   * @param string $name 名稱
   */
  public function __construct($name='') { $this->name = $name; }

  /**
   * 構建硬件
   *
   * @param  Hardware  $hardware 硬件參數
   * @return void
   */
  public function addHardware(Hardware $instance)
  {
    $this->hardwares[] = $instance;
  }

  /**
   * 構建軟件
   * 
   * @param  Software  $software 軟件參數
   * @return void
   */
  public function addSoftware(Software $instance)
  {
    $this->softwares[] = $instance;
  }
}


<?php
namespace builder;
use builder\Product;
/**
 * 產品構建器
 */
class ProductBuilder
{
  /**
   * 參數
   *
   * @var array
   */
  private $params = [
    'name'     => '',
    'hardware' => [],
    'software' => []
  ];

  /**
   * 構造函數
   */
  public function __construct($params = []) { }

  /**
   * mp3
   *
   * @param array $params 參數
   * @return Product Mp3
   */
  public function getMp3($params = [])
  {
    $this->params = $params;
    $mp3 = new Product($this->params['name']);
    $mp3->addHardware(new HardwareCpu($this->params['hardware']['cpu']));
    $mp3->addHardware(new HardwareRam($this->params['hardware']['ram']));
    $mp3->addHardware(new HardwareStorage($this->params['hardware']['storage']));
    $mp3->addSoftware(new SoftwareOs($this->params['software']['os']));
    return $mp3;
  }

  /**
   * phone
   * 
   * @param array $params 參數
   * @return Product Phone
   */
  public function getPhone($params = [])
  {
    $this->params = $params;
    $phone = new Product($this->params['name']);
    $phone->addHardware(new HardwareScreen($this->params['hardware']['screen']));
    $phone->addHardware(new HardwareCamera($this->params['hardware']['camera']));
    $phone->addHardware(new HardwareCpu($this->params['hardware']['cpu']));
    $phone->addHardware(new HardwareRam($this->params['hardware']['ram']));
    $phone->addHardware(new HardwareStorage($this->params['hardware']['storage']));
    $phone->addSoftware(new SoftwareOs($this->params['software']['os']));
    return $phone;
  }
}


<?php
namespace builder;
/**
 * 構建器接口
 */
Interface ProductInterface
{
  /**
   * 硬件構建
   * @return void
   */
  public function hardware();

  /**
   * 構建軟件
   * @return void
   */
  public function software();
}
二、定義產品概念類[2-Mp3Phone]、實現父級概念接口[ProductInterface],
<?php
namespace builder;
use builder\ProductInterface;
/**
 * Mp3構建器
 */
class Mp3 implements ProductInterface
{
  /**
   * 名稱
   * @var string
   */
  private $_name = '';

  /**
   * 處理器
   * @var string
   */
  private $_cpu = '';

  /**
   * 內存
   * @var string
   */
  private $_ram = '';

  /**
   * 儲存
   * @var string
   */
  private $_storage = '';

  /**
   * 系統
   * @var string
   */
  private $_os = '';

  /**
   * 構造函數
   *
   * @param string $name     名稱
   * @param array  $hardware 構建硬件
   * @param array  $software 構建軟件
   */
  public function __construct($name='', $hardware=array(), $software=array())
  {
    $this->_name = $name;
    $this->hardware($hardware);
    $this->software($software);
  }

  /**
   * 構建硬件
   *
   * @param  array  $hardware 硬件參數
   * @return void
   */
  public function hardware($hardware=array())
  {        
        $this->_cpu = new HardwareCpu($hardware['cpu']); // 建立 CPU
        $this->_ram = new HardwareRam($hardware['ram']); // 建立內存        
        $this->_storage = new HardwareStorage($hardware['storage']); // 建立存儲
  } 

  /**
   * 構建軟件
   * 
   * @param  array  $software 軟件參數
   * @return void
   */
  public function software($software=array())
  {    
    $softwareOs     = new SoftwareOs(); // 建立操做系統
    $this->_os      = $softwareOs->produce($software['os']);
  }
}
三、定義組件類[3-HardwareCpu、SoftwareOs...],
<?php
namespace builder;
/**
 * 處理器實體
 */
class HardwareCpu implements Hardware
{
    private $_quantity;
    public function __construct($quantity=8) { $this->_quantity = $quantity; }
}

<?php
namespace builder;
/**
* 硬件接口
*/
interface Hardware { }


<?php
namespace builder;
/**
 * 操做系統實體
 */
class SoftwareOs implements Software
{
    private $_os;
    public function produce($os='android') { $this->_os = $os; }
}

<?php
namespace builder;
/**
 * 軟件接口
 */
interface Software
{
  public function produce();
}
構建實例
<?php
/**
 * 建立型模式
 *
 * php建造者模式
 * 簡單對象構建複雜對象
 * 基本組件不變,可是組件之間的組合方式善變
 *
 * 下面咱們來構建手機和mp3
 *
 * // 手機簡單由如下構成
 * 手機 => 名稱,硬件, 軟件
 * // 硬件又由如下硬件構成
 * 硬件 => 屏幕,cpu, 內存, 儲存, 攝像頭
 * // 軟件又由如下構成
 * 軟件 => android, ubuntu
 *
 * * // mp3簡單由如下構成
 * 手機 => 名稱,硬件, 軟件
 * // 硬件又由如下硬件構成
 * 硬件 => cpu, 內存, 儲存
 * // 軟件又由如下構成
 * 軟件 => mp3 os
 */
 
// 註冊自加載
spl_autoload_register('autoload');
function autoload($class)
{
  require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php';
}
/************************************* test *************************************/
use builder\ProductBuilder;
$builder = new ProductBuilder();

// 生產一款mp3
$builder->getMp3([
  'name' => '某族MP3',
  'hardware' => [
    'cpu'     => 1,
    'ram'     => 1,
    'storage' => 128,
  ],
  'software' => ['os' => 'mp3 os']
]);

echo "\n";
echo "----------------\n";
echo "\n";

// 生產一款手機
$builder->getPhone([
  'name' => '某米8s',
  'hardware' => [
    'screen'  => '5.8',
    'camera'  => '2600w',
    'cpu'     => 4,
    'ram'     => 8,
    'storage' => 128,
  ],
  'software' => ['os' => 'android 6.0']
]);

產品構造器
與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。

b.結構型模式藉由一以貫之的方式來了解元件間的關係,以簡化設計:鏈接|接口選擇

6) [適配器模式] 處理類,替換原類調用,邏輯選擇接口、繼續處理;
7) [橋接模式**] 接口類,把多角度分類分離出來,讓它們獨立變化,減小它們之間耦合;
8) [過濾器模式] 處理類,批量遍歷、邏輯解耦;
9) [組合模式]:處理類,組合模式(Composite Pattern)能夠對象添加到另外一個的內含列表,用於層次結構管理:如樹形打印;
10) [裝飾器模式**] 處理類,包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外的功能;
11) [外觀模式] (Facade Pattern)處理類,該類提供了客戶端請求的簡化方法和對現有系統類方法的委託調用;

橋接模式(Bridge Pattern)實例

步驟 1 建立橋接實現接口,實現類
DrawAPI.java
public interface DrawAPI {
   public void drawCircle(int radius, int x, int y);
}
//建立實現了 DrawAPI 接口的實體橋接實現類。
RedCircle.java
public class DrawRedCircle implements DrawAPI {
   @Override
   public void drawCircle(int radius, int x, int y) {
      System.out.println("Drawing Circle[ color: red, radius: "
         + radius +", x: " +x+", "+ y +"]");
   }
}
GreenCircle.java
public class DrawGreenCircle implements DrawAPI {
   @Override
   public void drawCircle(int radius, int x, int y) {
      System.out.println("Drawing Circle[ color: green, radius: "
         + radius +", x: " +x+", "+ y +"]");
   }
}
步驟 2 建立抽象類 Shape,使用 DrawAPI 接口
Shape.java
public abstract class Shape {
   protected DrawAPI drawAPI;
   protected Shape(DrawAPI drawAPI){
      this.drawAPI = drawAPI;
   }
   public abstract void draw();  
}
//建立實現了 Shape 接口的實體類。
Circle.java
public class Circle extends Shape {
   private int x, y, radius;
 
   public Circle(int x, int y, int radius, DrawAPI drawAPI) {
      super(drawAPI); //parent(drawAPI);
      this.x = x;  
      this.y = y;  
      this.radius = radius;
   }
 
   public void draw() {
      drawAPI.drawCircle(radius,x,y);
   }
}
步驟 3 使用 Shape 和 DrawAPI 類畫出不一樣顏色的圓。
BridgePatternDemo.java
public class BridgePatternDemo {
   public static void main(String[] args) {
      Shape redCircle = new Circle(100,100, 10, new RedCircle());
      Shape greenCircle = new Circle(100,100, 10, new GreenCircle());
 
      redCircle.draw();
      greenCircle.draw();
   }
}

裝飾器模式(Decorator Pattern)裝飾器類

建立實現了 Shape 接口的抽象裝飾類。

ShapeDecorator.java
public abstract class ShapeDecorator implements Shape {
   protected Shape decoratedShape;
 
   public ShapeDecorator(Shape decoratedShape){
      this.decoratedShape = decoratedShape;
   }
 
   public void draw(){
      //do1
      decoratedShape.draw();
      //do2
   }  
}
相關文章
相關標籤/搜索