Techtalk#8: Design patterns in real life

Preview:

DESCRIPTION

A few patterns explained and shown in PHP and Javascript. Enjoy!

Citation preview

Design Patterns

Денис Княжев

Java (Java EE, Swing (desktop), JBoss, Tomcat, Glassfish, Spring, Hibernate, Google App Engine)Javascript (JQuery, JavascriptMVC)Databases (MySQL, PostgreSQL, Cassandra, Google Cloud Datastore)AndroidPHP (half-trainee: Apache, Zend 1x)IOS (trainee)C/C++ (trainee)

AreasHealthcareGISe-commerceSocial NetworkingGaming (sometime...)

Open sourceGithub -> denisk20http://programmer-dvorak.appspot.com/ (Javascript)Bullshit Bingo Champion (Android)Draw Graph (Java desktop)

Developer, open source enthusiast

1. Паттерны придумали умники у которых слишком

много времени?

2. Немного паттернов

a. Template method

b. Command

c. Composite

d. Visitor

3. Q&A

1. Паттерны придумали умники у которых слишком много времени?

1994C++, Smalltalk

Стандартные решения стандартных проблем

Слишком часто используются не к месту

2. Немного паттернов

a. Template method

b. Command

c. Composite

d. Visitor

Template Method (Hollywood principle)Don’t call us, we’ll call you

Challenge: сохранить заметку.

Заметки могут быть разных видов (текстовые, голосовые, фото и т.д.)

class TextNote{ private $date; private $text; public function save() { $dbNote = new DB_Note();

$dbNote->setDate($this->date); $dbNote->setText($this->text);

$dbNote->save(); }

class PhotoNote extends TextNote{ private $photo;

class VideoNote extends TextNote{ private $video;

protected function saveExtra( DB_Note $dbNote){}

$this->saveExtra($dbNote);

protected function saveExtra(DB_Note $dbNote){ $dbNote->setPhoto($this->photo));}

protected function saveExtra(DB_Note $dbNote){ $dbNote->setVideo($this->video);}

class TextNote{ private $date; private $text; public function save() { $dbNote = new DB_Note();

$dbNote->setDate($this->date); $dbNote->setText($this->text);

$dbNote->save(); }

class PhotoNote extends TextNote{ private $photo;

class VideoNote extends TextNote{ private $video;

protected abstract function getTag();

$dbNote->setTag($this->getTag());

protected function getTag(){ return "Photo";}

protected function getTag(){ return "Video";}

Template Method: Summary

Позволяет вынести в Parent class очень много логики => эффективный DRY(Do not Repeat Yourself)

Навязывает наследование

Command (Execute something later)

Challenge:

● возможность batch-сохранения изменения в заметках● возможность отмены изменений в заметках

interface Command{ public function execute();}

interface UndoableCommand extends Command{ public function undo();}

class EditTextCommand implements Command{ private $note;

private $oldText; private $newText;

public function execute(){ if(strcmp($this->note->text, $this->newText) === 0) { return; } $this->oldText = $this->note->text; $this->note->text = $this->newText;

$this->note->save();}

$commands = array();

$commands[] = $command1;$commands[] = $command2;$commands[] = $command3;//...

public function executeAll(){ foreach($commands as $command) { $command->execute(); }}

class UndoableEditTextCommand extends EditCommand implements UndoableCommand{ public function undo() { if(strcmp($this->note->text, $this->oldText) === 0) { return; }

$this->newText = $this->note->text; $this->note->text = $this->oldText;

$this->note->save(); }}

$commands = array();

$commands[] = $command1;$commands[] = $command2;$commands[] = $command3;//...

public function undoAll(){ foreach($commands as $command) { $command->undo(); }}

In Javascript the life is easierВсе функции - командыvag command = function(param1, param2) {...};command.call(this, “hello”, “world”);

Манипулировать функциями - естественноfunction doSomething(value1, value2, comparator) { if(comparator.call(this, value1, value2) > 0) { //do something } else { //do something else }}

Command: Summary

● Абстрагирует не данные, а действие

● “Отложенное” выполнение● Batch-запуск● Возможность отмены и т.д.

● Память

Composite: иерархии объектов

Challenge:

● возможность сохранения всего дерева заметок(Заметку, её комментарии, комментарии на комментарии и т.д.)

interface Note{ public function save();}

abstract class AbstractNote implements Note{ private $childNotes = array();

public function addChild(Note $note) { $this->childNotes[] = $note; }

private function saveInternal() { //saves this note }

public function save() { $this->saveInternal(); foreach($this->childNotes as $child) { $child->save(); } }}

class TextNote extends AbstractNote{ //...}

class PhotoNote extends AbstractNote{ //...}

class VideoNote extends AbstractNote{ //...}

$parent = new VideoNote();

$comment = new TextNote();$videoResponse = new VideoNote();$commentOnVideoResponse = new TextNote();

$videoResponse->addChild( $commentOnVideoResponse);

$parent->addChild($videoResponse);$parent->addChild($comment);

$parent->save();

Composite: Summary

● Позволяет выполнять операции над всей иерархией объектов

● Поощряет делать много небольших классов вместо нескольких больших

● Вся иерархия хранится в памяти

● Поощряет наследование

Visitor: разные операции над разными объектамиChallenge:

Text notes Photo notes

Render

Share

interface Visitor{ public function visitTextNote(TextNote $note); public function visitPhotoNote(PhotoNote $note);}

interface Note{ public function accept(Visitor $visitor);}

class TextNote implements Note{ private $text;

//...

public function accept(Visitor $visitor) { $visitor->visitTextNote($this); }}

class PhotoNote implements Note{ private $photo;

//...

public function accept(Visitor $visitor) { $visitor->visitPhotoNote($this); }}

class RenderVisitor implements Visitor{ public function visitTextNote(TextNote $note) { echo "<p>{$note->getText()}</p>"; }

public function visitPhotoNote(PhotoNote $note) { echo "<img src='{$note->getPhoto()->src}'></img>"; }}

class ShareVisitor implements Visitor{ private $account;

//...

public function visitTextNote(TextNote $note) { $account->shareText($note->getText()); }

public function visitPhotoNote(PhotoNote $note) { $image = $note->getImage(); $image = self::resizeImage($image); $account->shareImage($image); }}

$notes = array();$notes[] = new TextNote();$notes[] = new PhotoNote();

Visitor renderVisitor = new RenderVisitor();Visitor shareVisitor = new ShareVisitor($account);

$this->processAllNotes($renderVisitor, $notes); //render all$this->processAllNotes($shareVisitor, $notes); //share all

function processAllTextNotes(Visitor $visitor, array $notes){ foreach($notes as $note) { $note->accept($visitor); //magic (double dispatch) }}

Visitor: Summary

● Полностью разделяет алгоритм и структуру данных

● Выделяет “разные вкусы” одного и того же алгоритма для разных типов данных

● Большой● Страшный● Сложный

Big summary

Использовать pattern не по назначению - большее зло, чем не использовать вообще● Template Method - “don’t call us, we’ll call you”● Command - отложенный запуск● Composite - иерархии объектов● Visitor - разделение алторитма и структуры

данных

Thank you!

http://goo.gl/39FhrR