Просмотр поста

.
Delphinum
Пример
В качестве примера использования ООП приведу следующий. Мне он кажется наиболее простым и понятным, и в то же время лаконичным.

Задача: реализовать механизм перебора символов (брутфорса) с возможностью изменения символов без изменения кода. На пример имеются символы 123, нужно чтоб код вывел 123, 132, 213 и др.

Процедурник задумался бы скорее всего об алгоритмах перебора, проверки существования числа и разбора строки на компоненты. Объектнику достаточно было бы вспомнить принципы организации чисел в математике.

Предметная область:
Разряд - конкретная позиция числа;
Число - совокупность разрядов и символов числа на этих разрядах;
Символ числа - один из возможных символов, используемых при составлении числа.

На пример число 123ABC имеет 6 разрядов, символ на первом разряде (самый правый) имеет вид C, на втором B, на третьем A и т.д. Для данной системы счисления используются символы: 1, 2, 3, A, B, C что эквивалентно десятичной - 1, 2, 3, 4, 5, 6 - но вместо 4,5,6 используются буквы латинского алфавита.
Если к числу C добавляется единица, число увеличивается на разряд: C + 1 = 10.

Объектная реализация задачи:
/**
 * Класс представляет конкретный символ числа (конкретную цифру).
 */
class Discharge{
  /**
   * Набор символов для обозначения элемента числа. Упорядочен в порядке возрастания их весового коэффициента.
   * @var integer[]
   */
  protected $numerals = [1, 2, 3, 4, 5, 'A', 'B', 'C']; // Доступные символы
  /**
   * Текущий символ элемента числа. Не может быть больше, чем число символов.
   * @var integer
   */
  protected $point = 0;
  /**
   * Система счисления (число элементов массива $numerals)
   * @var integer
   */
  protected $numberSystem;
 
  function __construct(){
    $this->numberSystem = count($this->numerals);
  }
 
  /**
   * Возвращает текущее значение элемента числа.
   * @return string
   */
  public function getNumber(){
    return (string)$this->numerals[$this->point];
  }
 
  /**
   * Добавляет к элементу числа монаду (единицу)
   * @return boolean true - если число удачно инкрементированно, false - если инкрементация вызвала сброс элемента числа.
   */
  public function plus(){
    $this->point++;
    if($this->point == $this->numberSystem){
      $this->point = 0;
      return false;
    }
    return true;
  }
}
 
/**
 * Класс представляет собой совокупность символов числа (само число).
 */
class Number{
  /**
   * Массив элементов числа, упорядоченный по возрастанию разрядности.
   * @var Discharge[]
   */
  protected $number = [];
 
  /**
   * Длина числа.
   * @var integer
   */
  protected $length;
 
  /**
   * @param integer $length Длина числа
   */
  function __construct($length){
    $this->length = $length;
    for($i = 0; $i < $length; $i++){
      $this->number[] = new Discharge;
    }
  }
 
  /**
   * Метод увеличивает заданный разряд на монаду.
   * @param integer $discharge Номер разряда начиная с 0
   */
  protected final function incrementDischarge($discharge){
    if($discharge < $this->length){
      if(!$this->number[$discharge]->plus()){
        $this->incrementDischarge($discharge+1);
      }
    }
  }
 
  /**
   * Метод увеличивает число на монаду.
   */
  public function increment(){
    $this->incrementDischarge(0);
  }
 
  /**
   * Метод возвращает число.
   * @return string Текущее значение числа
   */
  public function showNumber(){
    $resultNumber = '';
    for($i=$this->length; $i--; ){
      $resultNumber .= $this->number[$i]->getNumber();
    }
    return $resultNumber;
  }
}
 
$n = new Number(5);
for($i=0; $i<10; $i++){
  echo $n->showNumber()."\n";
  $n->increment();
}
echo $n->showNumber()."\n";
 
/*
  Результат
11111
11112
11113
11114
11115
1111A
1111B
1111C
11121 - повышение разряда
11122
11123
*/