Недавно я всегда подвергался воздействию принципов или моделей программирования, таких как МОК (инверсия контроля), DI (инъекция зависимости), и это ядро знаменитых фреймворков Java Spring, Struts и т. Д. В ответ на это я проверял различные элементы в Википедии и заимствовали соответствующие книги из библиотеки. Прочитав их, у меня есть некоторое понимание. Теперь я объединю объяснения в книге и свою собственную обработку и разбираю их следующим образом:
Например
Описание проблемы:
Разработать систему, которая может генерировать отчеты в формате Excel или PDF в соответствии с различными требованиями, такими как ежедневные отчеты, ежемесячные отчеты и т. Д.
Решение:
В соответствии с принципом «ориентированного на интерфейс программирования», интерфейс и реализация должны быть разделены, то есть функция генерирования отчетов извлекается в общий интерфейс отчетов, и предоставляются две реализации, которые генерируют отчеты Excel и PDF в форматах Excel и PDF. Затем клиент получает соответствующую функцию печати отчетов через отчеты поставщика услуг.
Метод реализации:
Согласно вышеизложенному, получена следующая классовая диаграмма:
Реализация кода:
Interface Reportgenerator {public void Generate (таблица таблицы); } класс ExcelGenerator реализует ReportGenerator {public void Generate (Table Table) {System.out.println («генерировать отчет Excel ...»); }} класс pdfGenerator реализует ReportGenerator {public void Generate (таблица таблицы) {System.out.println («Сгенерировать отчет PDF ...»); }} class Reportservice {// Отвечает за создание генератора отчетов для конкретных потребностей частного отчетного генератора = new pdfgenerator (); // Частный статический отчет Generator = New ExcelGenerator (); public void getDailyreport (дата даты) {table.setDate (date); // ... генератор.generate (таблица); } public void getMonthlyReport (месяц месяца) {table.setmonth (месяц); // ... генератор.generate (таблица); / Reportservice.getDailyReport (New Date ()); //reportservice.getmonthlyreport(new date ()); }}
EG2
Описание проблемы:
Как показано в комментариях в приведенном выше коде, конкретный генератор отчетов создается с трудом кодируется внутри класса Reportservice, так что Reportservice напрямую полагался на PDFGenerator или ExcelGenerator, и это очевидное плотное соединение должно быть устранено.
Решение: введите контейнеры для введения промежуточного менеджера, то есть контейнера (контейнер), который равномерно управляет объектами, участвующими в системе отчетности (вот компонент, мы называем его бобовым), включая Reportservice и различные XxGenerators. Здесь вы используете экземпляр HashMap в форме пары клавиш, чтобы сохранить эти бобы.
Метод реализации:
Диаграмма класса получается следующим образом:
Реализация кода:
Класс-контейнер {// Сохранить различные необходимые компоненты в паре клавишных значений Bean Private Static Map <String, Object> Beans; public container () {beans = new Hashmap <String, Object> (); // Создание и сохранение конкретного генератора отчетов Отчет GEORTERATORTORATOREGENERATOR = NEW PDFGENERATOR (); beans.put ("ReportGenerator", ReportGenerator); // Получить и управлять ссылкой на отчеты Reportservice Reportservice = new Reportservice (); beans.put ("Reportservice", Reportservice); } public Static Object getBean (String Id) {return beans.get (id); }} class Reportservice {// Устранение напряженной связи связи и замените его контейнером // частного статического генератора Generator = new PdfGenerator (); Частный генератор генератора Generator generator = (ReportGenerator) Container.getBean ("ReportGenerator"); public void getDailyreport (дата даты) {table.setDate (date); Генератор.generate (таблица); } public void getMonthlyReport (месяц месяца) {table.setmonth (месяц); Генератор.generate (таблица); / Reportservice Reportservice = (Reportservice) Container.getbean ("Reportservice"); Reportservice.getDailyReport (New Date ()); //reportservice.getmonthlyreport(new date ()); }}
Таблица времени примерно следующим образом:
Эффект:
Как показано выше, Reportservice больше не связан с конкретным генератором Report. Он использовал контейнеры для изоляции интерфейса и реализации, улучшая возможности повторного использования системных компонентных бобов. В настоящее время вы также можете использовать файлы конфигурации для получения определения конкретных компонентов в контейнере в режиме реального времени.
EG3
Описание проблемы:
Однако, если вы посмотрите на приведенную выше диаграмму классов, легко обнаружить, что между Reportservice и контейнером существует двусторонняя связь, и они имеют взаимные зависимости. И, если вы хотите повторно использовать Reportservice, он также напрямую зависит от конкретной логики поиска одного контейнера. Если другие контейнеры имеют различные механизмы поиска компонентов (такие как JNDI), повторное использование Reportservice в настоящее время означает, что необходимо изменить внутреннюю логику поиска контейнера.
Решение: представление локатора обслуживания
Повторное представление локатора службы непрямого слоя используется для обеспечения интерфейса для логики поиска компонентов. Пожалуйста, смотрите описание в Википедии или его описание Java EE 1 и 2. Это позволит обеспечить возможную изоляцию возможных изменений.
Метод реализации:
Схема классов выглядит следующим образом:
Реализация кода:
// В фактическом приложении вы можете использовать интерфейс для предоставления унифицированного класса интерфейса ServiceLocator {Private Static Container Container = new Container (); Public Static ReportGenerator getReportGenerator () {return (ReportGenerator) Container.getBean ("reportGeneraTor"); }} class Reportservice {private reportGenerator of ReportGenerator = ServiceLocator.getReportGenerator (); // ...}EG4
Описание проблемы:
Однако, независимо от того, является ли он введением контейнера или использует локатор сервиса, Reportservice «активен» в поиске и создании определенных компонентов, что означает, что как клиент, отчеты должны быть ясны в отношении того, что ему нужно, где его можно получить, и как его можно получить. Внезапные, конкретные логические детали должны быть добавлены из -за того, что, где и как.
Например, в предыдущем методе реализации «Введение контейнера» есть следующий код:
Class Reportservice {// Устранение тесной связи связи и замените его контейнером // частного статического генератора отчетов GENERATOR = NEW PDFGENERATOR (); // Найти частный отчет Generator = (ReportGenerator) Контейнер .getBean ("ReportGenerator");
В методе реализации «Представление локатора службы» есть следующий код:
Класс ServiceLocator {PrivateStatic Container Container = новый контейнер (); Publicstatic ReportGenerator getReportGenerator () {// Это все еще intainer.getbean (), просто используется делегат return (ReportGenerator) Container.getBean ("ReportGeneraTor"); }} class Reportservice {// Reportservice В конце концов, он по -прежнему «активно» поиск и делегирует в ServiceLocator Private ReportGenerator generator generator = ServiceLocator.getReportGenerator (); }
Решение:
В этом случае изменение «активного» на «пассивное», несомненно, снизит внутренние знания Reportservice (то есть логика поиска компонентов). Согласно принципу инверсии управления (МОК), это притяжение (притяжение, активное) преобразуется в режим толкания (толкай, пассивный).
Например, подписка на RSS, которую мы обычно используем, представляет собой Push -приложение, которое экономит нам хлопот в регистрации в наш любимый сайт несколько раз в день, чтобы активно получать обновления статьи.
Инъекция зависимости (DI) достигает такого рода пассивного приема и уменьшает проблемы клиентов (здесь, Reportservice), содержащих сложную логику и слишком много знания.
Метод реализации:
Поскольку мы хотим быть «пассивным» приемом, мы должны вернуться к примеру контейнера без использования режима локатора службы. Модифицированная классовая диаграмма получена из этого следующим образом:
Оригинальная классовая диаграмма выглядит следующим образом. Вы можете проверить это и обратить внимание на подсказки для комментариев:
Реализация кода:
Чтобы позволить примеру быть скомпилированы и запустить, и использовать результаты выполнения кода отслеживания, чтобы явно создать всю классную диаграмму и сотрудничать друг с другом в последовательности, в конструктор каждого класса были добавлены множество пронумерованных печатных операторов и два незначительных класса: что является немного атакующим:
импортировать java.util.date; импортировать java.util.hashmap; импорт java.util.map; // Чтобы иметь возможность компилировать и запускать, есть еще два незначительных класса. Месяц класса {} таблица класса {publicvoid setDate (дата дата) {} publicvoid setMonth (месяц месяца) {}} // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- System.out.println("2...start initialization ExcelGenerator ... "); } publicvoid Generate (таблица таблицы) {System.out.println («генерировать отчет Excel ...»); }} класс pdfGenerator реализует reportgenerator {public pdfGenerator () {System.out.println ("2 ... начало инициализации pdfGenerator ..."); } publicVoid Generate (таблица таблицы) {System.out.println («Сгенерировать отчет PDF ...»); }} // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------. ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Получить и управлять ссылкой на отчеты Reportservice Reportservice = New Reportservice (); // внедрять конкретный экземпляр ReportGenerator, созданный выше Reportservice.setReportGenerator (ReportGenerator); beans.put ("Reportservice", Reportservice); System.out.println ("5 ... контейнер с инициализацией конечной инициализации ..."); } publicstatic Object getBean (String Id) {System.out.println ("Последнее получение сервисного компонента ... getBean () ->" + id + "..."); returnbeans.get (id); }} class Reportservice {// private static statice generator = new pdfgenerator (); // Устранение тесной связи с связью выше и замените его контейнером // частным генератором отчетов Generator = (ReportGenerator) // .GetBean ("ReportGenerator"); // Удалить «Активный» поиск выше и предоставить частные поля для сохранения внешнего объекта Генератора частного отчета; // Inject publicvoid из внешней части в форме сеттера SetReportGenerator (GESTERGENERATORE GENERATOR) {SYSTER.OUT.PRINTLN ("4 ... Start Inject viretGenerator ..."); this.Generator = генератор; } частная таблица = новая таблица (); public Reportservice () {System.out.println ("3 ... Start инициализация Reportservice ..."); } publicvoid getDailyReport (дата даты) {table.setDate (date); Генератор.generate (таблица); } publicvoid getMonthlyReport (месяц месяца) {table.setmonth (месяц); Генератор.generate (таблица); }} publicClass Client {publicstaticvoid main (string [] args) {// инициализировать контейнер new Container (); Reportservice Reportservice = (Reportservice) Контейнер .getbean ("Reportservice"); Reportservice.getDailyReport (New Date ()); // Reportservice.getMonthlyReport (New Date ()); }}
Результаты работы:
1 ... Контейнер для начала инициализации ... 2 ... Начальная инициализация PdfGenerator ... 3 ... Start Initiazation Reportservice ... 4 ... Start Inject ReportGenerator ... 5 ... Контейнер с инициализацией конечной инициализации ... наконец -то получите сервисный компонент ... getBean () -> Reportservice ... Создайте отчет PDF ...
Уведомление:
1. Согласно порядку печати приведенных выше результатов, можно видеть, что конкретное число, добавленное к коду, является разумным, что имитирует процесс выполнения программы, поэтому больше не рисует диаграммы последовательности.
2. Обратите внимание, что использование МОК и DI в этом примере основано на Reportservice в качестве клиента (то есть компонента Demander), а тестовый код в классе клиента () в коде является конечным пользователем компонента службы, но он не нуждается в компоненте, а сервисами, которые есть у компонента.
3. На самом деле, в зажиме Spring Box инициализация контейнера, очевидно, не то, что должен делать клиент конечного пользователя, его следует запустить поставщиком услуг.
4. В конкретных приложениях доступные компоненты обслуживания обычно развернуты на сервере с использованием XML и других файлов конфигурации, а затем файлы конфигурации читаются контейнером и в сочетании с технологией отражения для создания и введения конкретных компонентов обслуживания.
проанализировать:
Ранее Reportservice активно просила сервисную компонент из контейнера, но теперь он пассивно ждал, пока компонент обслуживания контейнера (то есть Push). Управление, очевидно, передается из базового модуля (Reportservice-это компонент Demander) в модуль высокого уровня (контейнер является поставщиком компонентов), то есть управление изменяется.