Краткие ответы: Состав по наследству . Программа против интерфейсов . Принцип наименьших привилегий . Ролевые интерфейсы .
Я бы посоветовал вам сделать гугл на них после прочтения моего поста;)
Во-первых, вам не нужно InputStream
наследовать от ViewController
, поскольку VieController.doSaveAsXML()
является общедоступным.
Даже если бы он имел частную | защищенную | видимость пакета, мы не должны использовать наследование только для доступа к методу какого-то другого класса, который нам не виден. Наследование предназначено для наследования , уточнения или расширения , а не для доступа к методам.
Вы всегда можете передать контроллер как тип аргумента в ваш поток ввода. Если ваш входной поток должен получить доступ ко всем методам в контроллере, передайте контроллер как есть (или попросите контроллер реализовать интерфейс со всеми методами в нем).
Первое, на что нужно обратить внимание , это то, что вашему InputStream
действительно не нужен доступ к контроллеру. Ему нужен только доступ к чему-то, что может выполнять для него функции file opening
- ему нужно file opener
.
Вторым важным моментом, на который следует обратить внимание , является то, что контроллеру (как правило) также не нужно знать, как открывать файлы. Контроллер обычно является организатором или оркестратором (из-за отсутствия лучшего слова). Таким образом, ему не нужно открывать файл (или реализовывать саму логику открытия файла). Контроллеру просто нужна ссылка на file opener
, Как и input stream
, controller
нужно просто делегировать file opening logic
file opener
.
Другими словами:
- ваш входной поток должен иметь
доступ к открывателю файлов
- ваш контроллер также должен только
иметь доступ к открывателю файлов
- ваш контроллер инициализирует ваш
входной поток, и так, он должен
передать ему открыватель файлов во время
инициализация
- из-за вышеизложенного контроллер
сам должен получить,
создается или быть настроен с
Сам инструмент для открытия файлов.
- поскольку средство открытия файлов является внешним по отношению к
и поток, и контроллер,
Средство открытия файлов должно быть
интерфейс (который может быть реализован
с помощью средства для открытия XML-файлов или любого другого
в этом отношении.)
псевдокод Java:
public interface FileOpener
{
public void doOpen();
}
public class XMLOpener implements FileOpener
{
public void doOpen(){ ... do xml specific file opening ... }
}
public interface Stream
{
/** inits stream with controller
**/
public void init(FileOpener FileOpener);
public void kickIt();
}
public interface Controller
{
// defines other methods implemented by actual interfaces.
public void kickIt();
}
public class ViewController implements Controller
{
private Stream stream;
private FileOpener opener;
public ViewController( final Stream stream. final FileOpener opener )
{
this.stream = stream;
this.opener = opener;
this.stream.init(this.opener);
}
public void kickIt(){ stream.kickIt() );
}
public class InputStream implements Stream
{
private FileOpener opener;
public InputStream()
{
}
public Stream init(final FileOpener opener )
{
this.opener = opener;
}
public void kickIt()
{
this.opener.doOpen();
}
}
....
Controller controller = new ViewController(
new InputStream(),
new XMLOpener() );
Идете ли вы до конца, заставляя все работать против обработчиков интерфейсов, это дизайнерское решение, которое мы должны принимать с каждым проектом. Но этот подход (или что-то вдохновленное этим), как правило, путь. Так гораздо сложнее (но не невозможно) придумать циклические зависимости, и когда они возникают, они являются вопросом конфигурации, а не внутренней проблемой вашей объектной модели.
Надеюсь, это поможет.