Эта статья иллюстрирует внедрение зависимостей PHP и контейнеры Ioc. Поделитесь для вашей справки следующим образом:
фон
Во многих языках программирования (таких как java) программистам необходимо полагаться на методы других классов в одном классе, обычно это метод вызова экземпляров класса из нового зависимого класса. Проблема такого рода разработки заключается в том, что экземпляры класса new плохо управляются. После изменения будет задействовано много классов.
Самая ранняя весна в Java Предложена идея внедрения зависимостей. То есть вместо создания экземпляров программистами классы зависимостей помогают нам указывать новые экземпляры через контейнеры spring и внедрять их в классы, которые в них нуждаются. В настоящее время многие основные фреймворки PHP также используют контейнеры для внедрения зависимостей, такие как ThinkPHP, Laravel и так далее.
I. Концепция
1. Контейнер: Буквально понимание-это то, что содержит вещи. Общие переменные, атрибуты объектов и т.д. Могут рассматриваться как контейнеры. То, что может вместить контейнер, полностью зависит от вашего определения контейнера. Конечно, то, что мы сейчас обсуждаем, – это контейнер, в котором не хранятся текстовые или числовые значения. Это описание (класс, интерфейс) объекта или обратный вызов (закрытие), который предоставляет объект. С помощью этого контейнера мы можем реализовать множество расширенных функций, среди которых часто упоминаются “развязка” и “внедрение зависимостей”.
2. IoC-Инверсия управления Инверсия управления
Инверсия управления описывается с точки зрения контейнеров, т. Е. приложений управления контейнерами, которые вводят внешние ресурсы, требуемые приложениями из контейнеров, в противоположном направлении.
3. Инъекция Зависимости от Зависимости Инъекция Зависимости
Внедрение зависимостей описывается с точки зрения приложения, которое может вводить зависимости, то есть приложение полагается на контейнер для создания и внедрения необходимых ему внешних ресурсов.
Примечания: Внедрение зависимостей и инверсия управления говорят об одном и том же Это шаблон проектирования, который используется для уменьшения связи между программами. С одной стороны, они описывают разные точки зрения. –
II. Принцип введения зависимостей
В общем случае, когда существует зависимость между классами, мы называем ее прямым созданием экземпляра. Как только возникают многослойные зависимости, степень связи этого подхода очень высока. Когда один из классов необходимо изменить, это потребует многих изменений класса, которые зависят от него, поэтому изменения кода будут относительно большими.
Вот простой пример трехуровневых отношений зависимости A-> B-> C, чтобы объяснить, как использовать внедрение зависимостей для разделения и повышения эффективности разработки.
Внедрение зависимостей выглядит следующим образом:
Анализ:
В обычной письменной форме, как только класс C необходимо изменить или вызовы класса B необходимо изменить на класс D, нам также необходимо рассмотреть возможность использования нашего собственного класса B, то есть нам необходимо внести изменения в класс B.
Идея внедрения зависимостей состоит в том, чтобы инвертировать отношения управления между классами, используя мгновенные экземпляры для управления последующими отношениями зависимостей путем вызова класса A, чтобы класс B мог изменять требуемую зависимость и создаваемый класс (класс C или класс D) по желанию для достижения развязки.
3. Часто используемые методы внедрения зависимостей:
1. Инъекция метода построения; 2. Инъекция атрибута набора; 3. Инъекция статического заводского метода;
В приведенном выше примере используется метод инъекции конструктора, который передает объект в качестве параметра конструктору; тот же метод инъекции атрибута набора аналогичен, за исключением того, что он передает параметр объекта при передаче атрибута члена класса набора.
Кроме того, существует метод впрыска статического заводского метода, который аналогичен статическому заводскому методу.
Мы знаем, что Статические методы фабрики управляют несколькими аналогичными классами, которые необходимо создать с помощью класса, определяющего метод получения объектов, которые необходимо создать Какой объект необходимо создать, зависит от переданного параметра имени объекта.
Для внедрения статического заводского режима В отличие от общего метода статической фабрики, этот входящий параметр является объектом, который был создан.
В целом, три способа доставки являются экземплярами объектов, но разница в том, что местом доставки является метод построения, атрибут набора, метод статической фабрики.
IV. Контейнер Для Инъекций Зависимостей (Контейнер Ioc)
В большинстве случаев контейнеры не нужны при использовании внедрения зависимостей для разделения компонентов. Когда программе требуется слишком много классов для создания экземпляра или слишком много зависимостей, повторение кода внедрения зависимостей утомительно, например, следующее:
Когда эти отношения создаются, код внедрения зависимостей сбивает с толку и дублируется, и более вероятно, что новый ненужный класс создаст избыточность при вызове общего метода.
На этом этапе нам нужно использовать контейнеры. После использования контейнеров для внедрения зависимостей идея заключается в том, что приложению необходимо перейти в класс A и получить класс A из контейнера. В частности, контейнер создает класс C, затем создает класс B и вводит класс C, затем создает класс A и вводит класс B. Приложение вызывает метод класса A, класс A вызывает метод класса B, а затем выполняет другую работу. Одним словом, контейнер отвечает за создание экземпляров, внедрение зависимостей и обработку зависимостей.
Для сложной и изменчивой среды кода в реальной разработке мы не можем полностью знать, во что будет расширяться текущий класс в будущем, поэтому нам необходимо реализовать метод создания экземпляра класса через контейнер при добавлении новых зависимых классов. Поэтому при создании экземпляров неизвестных классов лучшим способом изучения внутренней структуры и создания экземпляров класса является использование reflex Таким образом, отражение является ядром классов зависимостей управления контейнерами. Мы можем узнать о внутренней реализации контейнеров на примерах:
Три зависимых класса: тестовый класс файла. PHP
PHP // dependency: Company - > Department - > Group
class Group
{
public function doSomething()
{
echo __CLASS__.":".'hello', '|';
}
}
class Department
{
private $group;
public function __construct(Group $group)
{
$this->group = $group;
}
public function doSomething()
{
$this->group->doSomething();
echo __CLASS__.":".'hello', '|';
}
}
class Company
{
private $department;
public function __construct(Department $department)
{
$this->department = $department;
}
public function doSomething()
{
$this->department->doSomething();
echo __CLASS__.":".'hello', '|';
}
}Внутренняя реализация контейнера Ioc:
s[$k] = $c;
}
public function __get($k)
{
return $this->build($this->s[$k]);
}
/**
* Autowiring Automatic Resolution
*
* @param string $className
* @return object
* @throws Exception
*/
public function build($className)
{
// If it's an anonymous function, it's also called closures.
if ($className instanceof Closure) {
// Execute closure functions and generate results
return $className($this);
}
/* Get the inner structure of the class by reflection and instantiate the class*/
$reflector = new ReflectionClass($className);
// Check whether classes can be instantiated, excluding abstract classes and object interface
if (!$reflector->isInstantiable()) {
throw new Exception("Can't instantiate this.");
}
/ **@var ReflectionMethod $constructor Gets the constructor of the class*/
$constructor = $reflector->getConstructor();
// Without a constructor, instantiate directly and return
if (is_null($constructor)) {
return new $className;
}
// Take the constructor parameter and return the parameter list through the ReflectionParameter array
$parameters = $constructor->getParameters();
// Parameters of recursive analytic constructor
$dependencies = $this->getDependencies($parameters);
// Create a new instance of a class, and the parameters given will be passed to the constructor of the class.
return $reflector->newInstanceArgs($dependencies);
}
/**
* @param array $parameters
* @return array
* @throws Exception
*/
public function getDependencies($parameters)
{
$dependencies = [];
/** @var ReflectionParameter $parameter */
foreach ($parameters as $parameter) {
/** @var ReflectionClass $dependency */
$dependency = $parameter->getClass();
if (is_null($dependency)) {
// Is a variable, set the default if there is a default value
$dependencies[] = $this->resolveNonClass($parameter);
} else {
// Is a class, recursive parsing
$dependencies[] = $this->build($dependency->name);
}
}
return $dependencies;
}
/**
* @param ReflectionParameter $parameter
* @return mixed
* @throws Exception
*/
public function resolveNonClass($parameter)
{
// If there is a default value, the default value is returned.
if ($parameter->isDefaultValueAvailable()) {
return $parameter->getDefaultValue();
}
throw new Exception('I have no idea what to do here.');
}
}
Requ_once". / testclass. php"; // Start testing, first testing the known dependencies
$c = new Container();
$c->department = 'Department';
$c->company = function ($c) {
return new Company($c->department);
};
// Get company from container
$company = $c->company;
Company - > doSomething (); // Output: Group: Hello | Department: Hello | Company: hello|
// Test unknown dependencies, direct-use methods
$di = new Container();
$di->company = 'Company';
$company = $di->company;
Company - > doSomething (); // Output: Group: Hello | Department: Hello | Company: hello|Мы можем объяснить внутреннюю логику контейнера Ioc с помощью диаграммы:
V. Резюме
Основная концепция IOC заключается не в создании объектов, а в описании того, как они создаются. Он не подключается напрямую к объектам и службам в коде, но описывает в файле конфигурации, какие компоненты нуждаются в каких службах. Пружинный контейнер отвечает за их соединение. То есть, МОК Spring отвечает за управление созданием, очисткой и подключением различных объектов.
Больше читателей, интересующихся контентом, связанным с PHP, могут ознакомиться с темами этого сайта: Введение в объектно-ориентированное программирование Php, Введение в навыки работы с массивами PHP, Введение в базовую грамматику PHP, Краткое описание работы PHP и использования операторов, Краткое описание использования строк Php и данных php+mysql. Введение в библиотечные операции и Краткое описание общих навыков работы с базами данных на PHP
Я надеюсь, что эта статья будет полезна для разработки PHP – программ для всех.