Вступление
В предыдущей статье я написал о разных способах оформления интерфейсов к компонентам и сокрытия их реализации в C++.
В этой статье расскажу вкратце, как в Java отделить интерфейс от реализации, а реализацию скрыть.
Я не буду рассматривать компоненты разных там Java EE, я рассмотрю самые обычные jar-ники-библиотеки.
Итак.
Что мы имеем
В Java нет функций, есть только классы, соответственно в Java экспортируются классы.
Чтобы класс был экспортирован, нужно чтобы он был объявлен как public.
Итак, чтобы написать интерфейс библиотеки, нужна, собственно, сама библиотека и объявление экспортируемых классов как public.
Что-то типа того:
package com.test; public class Test { private final String string = "Test"; public String GetString() { return string; } }
Компилируем, получаем jar-ник, который затем может использовать.
Ну как-то так:
package com.sample; import com.test.Test; public class NewClass { private static Test test = new Test(); public static void Main() { System.out.println( test.GetString() ); } }
Какие в таком подходе недостатки.
Хоть скомпилированный jar-ник и скрывает реализацию, но у нас остаются доступными все public-методы классов библиотеки. Например если у нас jar-ник состоит из нескольких пакетов (Package-й), и мы использовали в нем вызовы методов между ними, то получится, что разработчик, использующий вашу библиотеку, сможет получить доступ к методам, которые вы не хотели открывать для использования. Т.е. мы опять же открываем реализацию. Так же мы не имеем текстов интерфейсов, которые бы могли отдать разработчикам для изучения.
Что делать в таком случае?
Чтобы полностью скрыть реализацию воспользуется одними из самых удобных инструментов Java — интерфейсами и рефлексией.
Что получилось
Например, у нас есть компонент с таким интерфейсом:
package com.iface; public interface Component { public void Method1(); public void Method2(); public void Method3(); public void Method4(); }
Экземпляры компонента создаем фабрикой, которая реализует вот такой интерфейс:
package com.iface; public interface Factory { public Component getComponent(); }
Экземпляр фабрики создаем статически. Ссылку на фабрику сохраняем. Оформляем классом FactoryCreator следующим образом:
package com.iface; import java.lang.reflect.Method; public class FactoryCreator { private static Factory instance = null; private static Throwable ex = null; static { try { Class cl = Class.forName("com.test.FactoryImpl"); Method method = cl.getMethod("createInstance", new Class[0]); Object obj = method.invoke(cl, new Object[0]); if(obj instanceof Factory) { instance = (Factory) obj; } ex = new Exception("Cannot init Factory instance."); } catch (Throwable throwable) { ex = throwable; } } public static Factory getInstance() throws Throwable { if(instance != null) { return instance; } throw ex; } }
Итак, как это работает и что у нас получилось.
Все интерфейсы оформляем в одной библиотеке, реализацию полностью оформляем в другой библиотеке. В единственном классе библиотеки интерфейсов статически получаем класс реализации фабрики по его имени. Затем по имени же получаем статический метод этого класса, который создает нам экземпляр фабрики. Вызываем этот метод и сохраняем экземпляр фабрики. Вызов getInstance() просто отдаст нам этот экземпляр. Можно изобрести много таких реализаций, но общая идея отсюда понятна. Для разработки и компиляции достаточно библиотеки интерфейсов. Так же, для удобства изучения, можно полностью раскрыть для разработчиков исходники интерфейсов.
Для запуска приложения нужно только указать java-машине, что помимо загрузки jar-ника с интерфейсами, нужно загрузить jar-ник с реализацией.
Резюме
Используя предложенный подход можно получить много плюсов в разработке. Ну взять хотя бы такую ситуацию. Мы ведем разработку сложной системы, в которой есть много взаимосвязанных компонентов.
Для параллельной разработки очень удобно разработать интерфейсы и сложить их в отдельные библиотеки. Тогда можно легко распараллелить разработку самих компонентов, их тестов, и компонентов, которые с ними связаны. Все будет прекрасно компилиться и собираться, хотя реализация при этом может быть еще не готова.
ссылка на оригинал статьи http://habrahabr.ru/post/161085/
Добавить комментарий