summaryrefslogtreecommitdiff
path: root/content/digarden/pages/20211210234818-dependency_injection.org
blob: fbac036df10f21db930f122e5d5d374032a30589 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
:PROPERTIES:
:ID:       49387584-0ee5-42ab-bc90-648062e74a91
:END:
#+title: Dependency Injection
* Dependency Injection
Часть инверсии контроля, которая занимается инициализацией объектов и их
зависимостей обычно в единственном экземпляре. Объекты обычно передают в
аргументах функций-конструкторов класса, а штука находящая объекты
называется сервис-локатором.

Суть паттерна заключается в том, чтобы не инициализировать лишний раз в
конструкторе объекты вручную и не инициализировать лишний раз экземпляры
классов в принципе (IoC).

*Сервис-контейнер* -- класс, инициализирующий различные объекты, которые в
последствии хранит в одном из своих полей.

*Сервис* -- объекты, управляемые сервис-контейнером.

*Реализации:*
+ Java
  http://picocontainer.com/
+ Python
  https://github.com/ets-labs/python-dependency-injector

*PHP и Symfony:*
http://fabien.potencier.org/what-is-dependency-injection.html
+ Dependency Injection без контейнеров
#+begin_src php
  class User
  {
    function __construct($storage)
    {
      $this->storage = $storage;
    }

    // ...
  }

  $storage = new SessionStorage('SESSION_ID');
  $user = new User($storage);
#+end_src

+ Реализация возврата объекта в единственном экземпляре
#+begin_src php
  class Container
  {
    static protected $shared = array();

    // ...

    public function getMailer()
    {
      if (isset(self::$shared['mailer']))
      {
	return self::$shared['mailer'];
      }

      $class = $this->parameters['mailer.class'];

      $mailer = new $class();
      $mailer->setDefaultTransport($this->getMailTransport());

      return self::$shared['mailer'] = $mailer;
    }
  }
#+end_src

+ Реализация сервис-контейнера
#+begin_src php
  class Container
  {
    static protected $shared = array();

    protected $parameters = array();

    public function __construct(array $parameters = array())
    {
      $this->parameters = $parameters;
    }

    public function getMailTransport()
    {
      return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
	'auth'     => 'login',
	'username' => $this->parameters['mailer.username'],
	'password' => $this->parameters['mailer.password'],
	'ssl'      => 'ssl',
	'port'     => 465,
      ));
    }

    public function getMailer()
    {
      if (isset(self::$shared['mailer']))
      {
	return self::$shared['mailer'];
      }

      $class = $this->parameters['mailer.class'];

      $mailer = new $class();
      $mailer->setDefaultTransport($this->getMailTransport());

      return self::$shared['mailer'] = $mailer;
    }
  }

#+end_src

*Ресурсы*
- Книга на 500+ страниц про Dependency Injection
  https://livebook.manning.com/book/dependency-injection/

** DI фреймворки и библиотеки
*** PHP
- [[https://github.com/silexphp/Pimple][Pimple]] (Минималистичный DI контейнер)