<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>框架模式 &#8211; 有意与无意之间</title>
	<atom:link href="https://zhangxihai.cn/archives/tag/%E6%A1%86%E6%9E%B6%E6%A8%A1%E5%BC%8F/feed" rel="self" type="application/rss+xml" />
	<link>https://zhangxihai.cn</link>
	<description>千淘万漉虽辛苦 吹尽狂沙始到金 - 生命不息 编程不止</description>
	<lastBuildDate>Fri, 08 Jan 2021 03:04:58 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.11</generator>
	<item>
		<title>PHP框架模式1：管道模式</title>
		<link>https://zhangxihai.cn/archives/84</link>
					<comments>https://zhangxihai.cn/archives/84#respond</comments>
		
		<dc:creator><![CDATA[胖爷]]></dc:creator>
		<pubDate>Tue, 29 Jan 2019 10:23:20 +0000</pubDate>
				<category><![CDATA[编码]]></category>
		<category><![CDATA[框架模式]]></category>
		<guid isPermaLink="false">https://zhangxihai.cn/?p=84</guid>

					<description><![CDATA[计算机领域内管道模式其本质大体和现实领域的管道系统相同：栽荷从从抽象的管道的一端流入，经过一系列的处理，最终从管道的另一端流出。 管道模式的形式有很多种，常见的有： 进程间管道，通常用于兄弟进程、亲缘进程、父子进程及子进程之间的通讯； 凹型管道，用于客户端与服务端的业务流程处理及通讯； 直线型管道，用于客户端或服务端的一般流程性业务处理； 直线型的管道模式又...]]></description>
										<content:encoded><![CDATA[<p>计算机领域内管道模式其本质大体和现实领域的管道系统相同：栽荷从从抽象的管道的一端流入，经过一系列的处理，最终从管道的另一端流出。</p>
<p>管道模式的形式有很多种，常见的有：</p>
<ul>
<li>进程间管道，通常用于兄弟进程、亲缘进程、父子进程及子进程之间的通讯；</li>
<li>凹型管道，用于客户端与服务端的业务流程处理及通讯；</li>
<li>直线型管道，用于客户端或服务端的一般流程性业务处理；</li>
</ul>
<p>直线型的管道模式又可以分为自治型管道模式和约定型管道模式, 而绝大多数框架中提供的管道模式都是自治直线型管道，它通常被在同一个项目内结束的业务过程所使用，从而动态地组合碎片化的业务流程。。</p>
<p>自治型管道中的所有处理对象都是由自己添加，内部结构以及前后衔接都是由自己控制，以下示例参考Laravel的实现：</p>
<pre><code class="language-php">&lt;?php

class Pipeline
{
    /**
     * 栽荷
     *
     * @var mixed
     */
    protected $passable;

    /**
     * 管道
     *
     * @var array
     */
    protected $pips = [];

    /**
     * 管道委托方法
     *
     * @var string
     */
    protected $method = &#039;handle&#039;;

    /**
     * 设置管道要调用的方法
     *
     * @param string $method
     * @return $this
     */
    public function via(string $method)
    {
        $this-&gt;method = $method;

        return $this;
    }

    /**
     * 发送栽荷
     *
     * @param $passable
     * @return $this
     */
    public function send($passable)
    {
        $this-&gt;passable = $passable;

        return $this;
    }

    /**
     * 运行管道并执行回调
     *
     * @param Closure $destination
     * @return mixed
     */
    public function then(Closure $destination)
    {
        $pipeline = array_reduce(
            array_reverse($this-&gt;pipes()), $this-&gt;carry(), $this-&gt;prepareDestination($destination)
        );

        return $pipeline($this-&gt;passable);
    }

    /**
     * 运行回调并返回栽荷
     *
     * @return mixed
     */
    public function thenReturn()
    {
        return $this-&gt;then(function ($passable) {
            return $passable;
        });
    }

    /**
     * 设置管道数组
     *
     * @param $pipes
     * @return $this
     */
    public function through($pipes)
    {
        $this-&gt;pipes = is_array($pipes) ? $pipes : func_get_args();

        return $this;
    }

    /**
     * 管道委托调用
     *
     * @return Closure
     */
    protected function carry()
    {
        return function ($stack, $pipe) {
            return function ($passable) use ($stack, $pipe) {
                if (is_callable($pipe)) {
                    // 管道可调用，例如方法，则直接调用
                    return $pipe($passable, $stack);
                } else if (!is_object($pipe)) {
                    [$name, $parameters] = $this-&gt;parsePipeString($pipe);
                    $pipe       = new $name();
                    $parameters = array_merge([$passable, $stack], $parameters);
                } else {
                    $parameters = [$passable, $stack];
                }
                return method_exists($pipe, $this-&gt;method) ? $pipe-&gt;{$this-&gt;method}(...$parameters) : $pipe(...$parameters);
            };
        };
    }

    /**
     * 从字符串获取类名和参数
     *
     * @param $pipe
     * @return array
     */
    protected function parsePipeString($pipe)
    {
        [$name, $parameters] = array_pad(explode(&#039;:&#039;, $pipe, 2), 2, []);

        if (is_string($parameters)) {
            $parameters = explode(&#039;,&#039;, $parameters);
        }

        return [$name, $parameters];
    }
}
</code></pre>
<p>相比较传统的<code>new pipeline()-&gt;pipe($callable)-&gt;pipe($obj)-&gt;process($passable)</code> 这种链式调用，Laravel的实现非常的巧妙，它先反转了存储管道的数组，将最后加入管道封装为函数，作为上一个管道封装函数的参数， 直到最先加入的管道， 这样就形成了一条调用链， 而回调则作为array_reduce的第一个参数一直向下传递。</p>
<p>使用自治型管道模式</p>
<pre><code class="language-php">&lt;?php

function filter1()
{ 
    $passable[] = &#039;采蘑菇的小姑娘&#039;;
    return $passable;
}

class filter2
{
    public function handle($passable, $message)
    {
        $passable[] = $message;
        return $passable;
    }
}

function callback($passable)
{
    var_dump($passable);
}

$pipes = [
     filter1(),
    &#039;filter2:爱吃鱼的大脸猫&#039;
];
(new Pipeline())-&gt;send([&#039;载荷&#039;])-&gt;through($pipes)-&gt;then(callback());</code></pre>
<hr />
<p><strong>自治直线型管道模式与责任链模式及过滤器模式的联系与区别</strong></p>
<p>管道模式可以实现责任链和过滤器模式所实现的功能，但管道模式作为框架模式，它有更高的层级，所以管道模式通常用于与其他开发者之间的共识的约定， 例如Laravel的中间件。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zhangxihai.cn/archives/84/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
