PrimePrinter
In questo esempio vedremo l'applicazione del principio SRP (Single Responsibility Principle) per la creazione di un sistema che si occupa di generare e stampare, sotto forma di righe-colonne, i primi 1000 numeri primi.
PrimeGenerator
<?php
/**
* Questa classe genera dei numeri primi fino a un massimo specificato dall'utente.
* L'algoritmo usato è il Setaccio di Eratostene.
* Dato un array di interi a partire da 2:
* - trova il primo intero non eliminato ed elimina tutti i suoi multipli
* - ripeti finché non vi sono più multipli nell'array
*/
class PrimeGenerator
{
private static $crossedOut = [];
private static $result = [];
public static function generate(int $maxValue): array
{
if ($maxValue < 2) {
return [];
}
self::uncrossIntegersUpTo($maxValue);
self::crossOutMultiples();
self::putUncrossedIntegersIntoResult();
return self::$result;
}
private static function uncrossIntegersUpTo(int $maxValue): void
{
for ($i = 0; $i < $maxValue + 1; $i++) {
self::$crossedOut[$i] = false;
}
}
private static function crossOutMultiples(): void
{
$limit = self::determineIterationLimit();
for ($i = 2; $i <= $limit; $i++) {
if (self::notCrossed($i)) {
self::crossOutMultiplesOf($i);
}
}
}
/**
* Ogni multiplo nell'array ha un fattore primo che è minore o uguale alla radice
* delle dimensioni dell'array, così che possiamo evitare di eliminare i multipli
* dei numeri maggiori di tale radice
* @return int
*/
private static function determineIterationLimit(): int
{
return (int)sqrt(count(self::$crossedOut));
}
private static function notCrossed(int $i): bool
{
return self::$crossedOut[$i] === false;
}
private static function crossOutMultiplesOf(int $i): void
{
for ($multiple = 2 * $i; $multiple < count(self::$crossedOut); $multiple += $i) {
self::$crossedOut[$multiple] = true;
}
}
private static function putUncrossedIntegersIntoResult()
{
for ($j = 0, $i = 2; $i < count(self::$crossedOut); $i++) {
if (self::notCrossed($i)) {
self::$result[$j++] = $i;
}
}
}
}
RowColumnPagePrinter
<?php
class RowColumnPagePrinter
{
private $rowsPerPage;
private $columnsPerPage;
private $numbersPerPage;
private $pageHeader;
private $data;
public function __construct(
int $rowsPerPage,
int $columnsPerPage,
string $pageHeader,
array $data
) {
$this->rowsPerPage = $rowsPerPage;
$this->columnsPerPage = $columnsPerPage;
$this->numbersPerPage = $rowsPerPage * $columnsPerPage;
$this->pageHeader = $pageHeader;
$this->data = $data;
}
public function print(): void
{
$pageNumber = 1;
for ($firstIndexOnPage = 0; $firstIndexOnPage < count($this->data); $firstIndexOnPage += $this->numbersPerPage) {
$lastIndexOnPage = min(($firstIndexOnPage + $this->numbersPerPage) - 1, count($this->data) - 1);
$this->printPageHeader($pageNumber);
$this->printPage($firstIndexOnPage, $lastIndexOnPage);
echo nl2br(PHP_EOL);
$pageNumber++;
}
}
private function printPageHeader(int $pageNumber): void
{
echo nl2br($this->pageHeader . ' --- Page ' . $pageNumber . PHP_EOL);
echo nl2br(PHP_EOL);
}
private function printPage(int $firstIndexOnPage, int $lastIndexOnPage): void
{
$firstIndexOfLastRowOnPage = ($firstIndexOnPage + $this->rowsPerPage) - 1;
for ($firstIndexInRow = $firstIndexOnPage; $firstIndexInRow <= $firstIndexOfLastRowOnPage; $firstIndexInRow++) {
$this->printRow($firstIndexInRow, $lastIndexOnPage);
echo nl2br(PHP_EOL);
}
}
private function printRow(int $firstIndexInRow, int $lastIndexOnPage): void
{
for ($column = 0; $column < $this->columnsPerPage; $column++) {
$index = $firstIndexInRow + ($column * $this->rowsPerPage);
if ($index <= $lastIndexOnPage) {
echo sprintf('%10d', $this->data[$index]);
}
}
}
}
PrimePrinter
<?php
require_once('./PrimeGenerator.php');
require_once('./RowColumnPagePrinter.php');
class PrimePrinter
{
private const ROWS_PER_PAGE = 10;
private const COLUMNS_PER_PAGE = 4;
private $rowColumnPagePrinter;
public function __construct(int $numberOfPrimes)
{
$primes = PrimeGenerator::generate($numberOfPrimes);
$this->rowColumnPagePrinter = new RowColumnPagePrinter(
self::ROWS_PER_PAGE,
self::COLUMNS_PER_PAGE,
'The First ' . $numberOfPrimes . ' Prime Numbers',
$primes
);
}
public function __invoke(): void
{
$this->rowColumnPagePrinter->print();
}
}
Index
<?php
require_once('./PrimePrinter.php');
$numberOfPrimes = 1000;
$primePrinter = new PrimePrinter($numberOfPrimes);
$primePrinter();
Last updated