chippyash/Assembly-Builder

View on GitHub
examples/CarAssemblyLine.php

Summary

Maintainability
A
2 hrs
Test Coverage
#!/usr/bin/env php
<?php
/**
 * Lightweight assembly builder pattern
 *
 * Car Assembly Line example using the Assembly Comprehension
 * This example illustrates a synchronous execution of the Comprehension
 *
 * Look - no If statements!
 *
 * @author Ashley Kitson
 * @copyright Ashley Kitson <ashley@zf4.biz>, 2015, UK
 * @licence GPLV3+ see LICENSE.MD
 */
include __DIR__ . '/../vendor/autoload.php';

use Assembler\Assembler;
use Assembler\FFor;
use Monad\FMatch;

class StringHolder
{
    /**
     * @var string
     */
    protected $val;

    public function __construct(string $val)
    {
        $this->val = $val;
    }

    public function __toString()
    {
        return $this->val;
    }
}

class Tyre extends StringHolder {}
class PaintColour extends StringHolder {}
class Car extends StringHolder {}

interface Carmaker
{
    /**
     * @param Assembler $assembler
     * @return Assembler
     */
    public function giveMe(Assembler $assembler);
}

class TyreMaker implements Carmaker
{
    /**
     * @param Assembler $assembler
     * @return \Closure
     */
    public function giveMe(Assembler $assembler)
    {
        return $assembler->tyre(
            FMatch::on(mt_rand(1,2))
            ->test(1, function(){return function(){return new Tyre('radial');};})
            ->test(2, function(){return function(){return new Tyre('cross-ply');};})
            ->value()
        );
    }
}

class Paintshop implements Carmaker
{
    /**
     * @param Assembler $assembler
     * @return \Closure
     */
    public function giveMe(Assembler $assembler)
    {
        return $assembler->colour(
            FMatch::on(mt_rand(1,2))
            ->test(1, function(){return function(){return new PaintColour('red');};})
            ->test(2, function(){return function(){return new PaintColour('black');};})
            ->value()
        );
    }
}

class AssemblyLine
{
    /**
     * @param Assembler $assembler
     * @return Car
     */
    public function make(Assembler $assembler)
    {
        list($tyre, $colour) = $assembler->assemble()
            ->release('tyre', 'colour');

        return new Car("I made you a $colour car with $tyre tyres");
    }
}

echo FFor::create()
    ->assembler(function(){return Assembler::create();})
    ->tyre(function($assembler){return (new TyreMaker)->giveMe($assembler);})
    ->colour(function($assembler){return (new Paintshop)->giveMe($assembler);})
    ->assemblyLine(function($assembler){return (new AssemblyLine)->make($assembler);})
    ->fyield('assemblyLine');