Шаблон Factory Method

Проблема:

Давайте представим, что перед нами стоит задача представления даных в виде html страницы, xml файла и, к примеру, как csv файл и нам нужно написать класс, который будет вызывать нужный нам класс для отображения даных. Назвем наши классы HtmlDataView, XmlDataView, CsvDataView соответственно. Часто программисты для этой задачи используют либо условные операторы, либо switch-оператор. Назвем главный класс для обработки даных DataViewManager. Следующий код показывает, как можно решить эту задачу неправельным путем.

interface DataView {
	public function view();
}

class HtmlDataView implements DataView {
	public function view () {
		//view data in html format
	}
}

class XmlDataView implements DataView {
	public function view () {
		//view data in xml format
	}
}

class CsvDataView implements DataView {
	public function view () {
		//view data in csv format
	}
}

class DataViewManager {
	const HTML = 1;
	const XML = 2;
	const CSV = 3;
	
	private $mode = 1;
	
	public function __construct($mode) {
		$this->mode = $mode;
	}
	
	public function getDataView () {
		switch($this->mode) {
			case self::XML:
				return new XmlDataView();
			case self::CSV:
				return new CsvDataView();
			default : 
				return new HtmlDataView();
		}
	}
}

Как видите, при добавлении функций, которым так же понадобится выбор схемы представления даных, нам придется писать обратно код, который будет дублироватся снова и снова.

Решение:

Для решения этой тривиальной задачи, как вы поняли, используется шаблон Factory Method. Главное правило хорошего программиста говорит, что нужно программировать на интерфейсах. Поэтому сделаем наш класс DataViewManager интерфейсом и на базе него создадим соответственно класи HtmlDataViewManager, XmlDataViewManager, CsvDataViewManager, что позволит нам создавать удобочетаемый код без розмножения условных операторов и операторов switch.

interface DataView {
	public function view();
}

class HtmlDataView implements DataView {
	public function view () {
		//view data in html format
	}
}

class XmlDataView implements DataView {
	public function view () {
		//view data in xml format
	}
}

class CsvDataView implements DataView {
	public function view () {
		//view data in csv format
	}
}

interface DataViewManager {
	public function getDataView();
	//other functions to implement
}

class HtmlDataViewManager implements DataViewManager {
	public function getDataView() {
		return new HtmlDataView();
	}
}

class XmlDataViewManager implements DataViewManager {
	public function getDataView() {
		return new XmlDataView();
	}
}

class CsvDataViewManager implements DataViewManager {
	public function getDataView() {
		return new CsvDataView();
	}
}

Следовательно, можна сказать, что в шаблонe Factory Method классы создателей отделены от продуктов, которые они должны генерировать. Создатель - это класс фабрики, в котором определен метод для генерации обьекта-продукта.

Схему шаблона Factory Method вы можете увидеть вначале страницы.

Недостатки:

Шаблон Factory Method часто способствует ненужному созданию подклассов.

LikeMe: