3v4l.org

run code in 300+ PHP versions simultaneously
<?php namespace RefactoringGuru\Flyweight\RealWorld; /** * Объекты Легковеса представляют данные, разделяемые несколькими объектами * Кошек. Это сочетание породы, цвета, текстуры и т.д. */ class CatVariation { /** * Так называемое «внутреннее» состояние. */ public $breed; public $image; public $color; public $texture; public $fur; public $size; public function __construct( string $breed, string $image, string $color, string $texture, string $fur, string $size ) { $this->breed = $breed; $this->image = $image; $this->color = $color; $this->texture = $texture; $this->fur = $fur; $this->size = $size; } /** * Этот метод отображает информацию о кошке. Метод принимает внешнее * состояние в качестве аргументов. Остальная часть состояния хранится * внутри полей Легковеса. * * Возможно, вы удивлены, почему мы поместили основную логику кошки в класс * РазновидностейКошек вместо того, чтобы держать её в классе Кошки. Я * согласен, это звучит странно. * * Имейте в виду, что в реальной жизни паттерн Легковес может быть либо * реализован с самого начала, либо принудительно применён к существующему * приложению, когда разработчики понимают, что они столкнулись с проблемой * ОЗУ. * * Во втором случае вы получаете такие же классы, как у нас. Мы как бы * «отрефакторили» идеальное приложение, где все данные изначально * находились внутри класса Кошки. Если бы мы реализовывали Легковес с * самого начала, названия наших классов могли бы быть другими и более * определёнными. Например, Кошка и КонтекстКошки. * * Однако действительная причина, по которой основное поведение должно * проживать в классе Легковеса, заключается в том, что у вас может вообще * не быть объявленного класса Контекста. Контекстные данные могут храниться * в массиве или какой-то другой, более эффективной структуре данных. */ public function renderProfile(string $name, string $age, string $owner) { echo "= $name =\n"; echo "Age: $age\n"; echo "Owner: $owner\n"; echo "Breed: $this->breed\n"; echo "Image: $this->image\n"; echo "Color: $this->color\n"; echo "Texture: $this->texture\n"; } } /** * Контекст хранит данные, уникальные для каждой кошки. * * Создавать отдельный класс для хранения контекста необязательно и не всегда * целесообразно. Контекст может храниться внутри громоздкой структуры данных в * коде Клиента и при необходимости передаваться в методы легковеса. */ class Cat { /** * Так называемое «внешнее» состояние. */ public $name; public $age; public $owner; /** * @var CatVariation */ private $variation; public function __construct(string $name, string $age, string $owner, CatVariation $variation) { $this->name = $name; $this->age = $age; $this->owner = $owner; $this->variation = $variation; } /** * Поскольку объекты Контекста не владеют всем своим состоянием, иногда для * удобства вы можете реализовать несколько вспомогательных методов * (например, для сравнения нескольких объектов Контекста между собой). */ public function matches(array $query): bool { foreach ($query as $key => $value) { if (property_exists($this, $key)) { if ($this->$key != $value) { return false; } } elseif (property_exists($this->variation, $key)) { if ($this->variation->$key != $value) { return false; } } else { return false; } } return true; } /** * Кроме того, Контекст может определять несколько методов быстрого доступа, * которые делегируют исполнение объекту-Легковесу. Эти методы могут быть * остатками реальных методов, извлечённых в класс Легковеса во время * массивного рефакторинга к паттерну Легковес. */ public function render(): string { $this->variation->renderProfile($this->name, $this->age, $this->owner); } } /** * Фабрика Легковесов хранит объекты Контекст и Легковес, эффективно скрывая * любое упоминание о паттерне Легковес от клиента. */ class CatDataBase { /** * Список объектов-кошек (Контексты). */ private $cats = []; /** * Список вариаций кошки (Легковесы). */ private $variations = []; /** * При добавлении кошки в базу данных мы сначала ищем существующую вариацию * кошки. */ public function addCat( string $name, string $age, string $owner, string $breed, string $image, string $color, string $texture, string $fur, string $size ) { $variation = $this->getVariation($breed, $image, $color, $texture, $fur, $size); $this->cats[] = new Cat($name, $age, $owner, $variation); echo "CatDataBase: Added a cat ($name, $breed).\n"; } /** * Возвращаем существующий вариант (Легковеса) по указанным данным или * создаём новый, если он ещё не существует. */ public function getVariation( string $breed, string $image, $color, string $texture, string $fur, string $size ): CatVariation { $key = $this->getKey(get_defined_vars()); if (!isset($this->variations[$key])) { $this->variations[$key] = new CatVariation($breed, $image, $color, $texture, $fur, $size); } return $this->variations[$key]; } /** * Эта функция помогает генерировать уникальные ключи массива. */ private function getKey(array $data): string { return md5(implode("_", $data)); } /** * Ищем кошку в базе данных, используя заданные параметры запроса. */ public function findCat(array $query) { foreach ($this->cats as $cat) { if ($cat->matches($query)) { return $cat; } } echo "CatDataBase: Sorry, your query does not yield any results."; } } /** * Клиентский код. */ $db = new CatDataBase(); echo "Client: Let's see what we have in \"cats.csv\".\n"; // Чтобы увидеть реальный эффект паттерна, вы должны иметь большую базу данных с // несколькими миллионами записей. Не стесняйтесь экспериментировать с кодом, // чтобы увидеть реальные масштабы паттерна. $handle = fopen(__DIR__ . "/cats.csv", "r"); $row = 0; $columns = []; while (($data = fgetcsv($handle)) !== false) { if ($row == 0) { for ($c = 0; $c < count($data); $c++) { $columnIndex = $c; $columnKey = strtolower($data[$c]); $columns[$columnKey] = $columnIndex; } $row++; continue; } $db->addCat( $data[$columns['name']], $data[$columns['age']], $data[$columns['owner']], $data[$columns['breed']], $data[$columns['image']], $data[$columns['color']], $data[$columns['texture']], $data[$columns['fur']], $data[$columns['size']], ); $row++; } fclose($handle); // ... echo "\nClient: Let's look for a cat named \"Siri\".\n"; $cat = $db->findCat(['name' => "Siri"]); if ($cat) { $cat->render(); } echo "\nClient: Let's look for a cat named \"Bob\".\n"; $cat = $db->findCat(['name' => "Bob"]); if ($cat) { $cat->render(); }

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
8.5.10.0090.01016.65
8.5.00.0140.00920.15
8.4.150.0030.00014.05
8.4.140.0110.01317.79
8.4.130.0090.00618.14
8.4.120.0120.00820.68
8.4.110.0080.01322.70
8.4.100.0130.00917.99
8.4.90.0110.01118.83
8.4.80.0110.01018.30
8.4.70.0110.00818.39
8.4.60.0060.01018.93
8.4.50.0050.00620.78
8.4.40.0100.00719.65
8.4.30.0030.00520.63
8.4.20.0040.01520.72
8.4.10.0090.00019.51
8.3.280.0110.01018.59
8.3.270.0120.00816.79
8.3.260.0130.00716.69
8.3.250.0070.01019.17
8.3.240.0050.00316.93
8.3.230.0110.00916.69
8.3.220.0120.00618.95
8.3.210.0040.00318.71
8.3.200.0040.00416.82
8.3.190.0100.00917.10
8.3.180.0080.01016.72
8.3.170.0120.00317.38
8.3.160.0150.00318.40
8.3.150.0150.00317.12
8.3.140.0150.00316.97
8.3.130.0040.00716.82
8.3.120.0090.00020.53
8.3.110.0050.00516.78
8.3.100.0000.00916.71
8.3.90.0000.00826.77
8.3.80.0090.00318.55
8.3.70.0080.00816.86
8.3.60.0140.00716.88
8.3.50.0110.00718.07
8.3.40.0130.00318.93
8.3.30.0100.00618.71
8.3.20.0040.00424.18
8.3.10.0050.00324.66
8.3.00.0050.00326.16
8.2.290.0110.01120.50
8.2.280.0100.01018.43
8.2.270.0100.01017.44
8.2.260.0040.00420.72
8.2.250.0080.00018.60
8.2.240.0030.00617.41
8.2.230.0030.00620.94
8.2.220.0030.00624.06
8.2.210.0060.01326.77
8.2.200.0030.00618.66
8.2.190.0110.00418.66
8.2.180.0070.01125.92
8.2.170.0120.00319.06
8.2.160.0210.00022.96
8.2.150.0040.00425.66
8.2.140.0080.00024.66
8.2.130.0040.00426.16
8.2.120.0040.00420.91
8.2.110.0090.00020.52
8.2.100.0070.00419.27
8.1.330.0110.00822.16
8.1.320.0100.00916.31
8.1.310.0000.01518.57
8.1.300.0100.01018.36
8.1.290.0040.00430.84
8.1.280.0090.00625.92
8.1.270.0040.00423.82
8.1.260.0060.00326.35
8.1.250.0040.00428.09
8.1.240.0060.00618.40
8.1.230.0040.00722.32
8.0.90.0040.00416.95

preferences:
105.3 ms | 403 KiB | 5 Q