Внутренние классы используют метод внешнего класса. Это циклическая ссылка? Как избежать

1

Мне было интересно, следует ли считать неправильную практику вызовом метода внешнего класса во внутреннем классе, а затем использовать внутренний метод класса во внешнем классе.

В этом случае: В BidParser я вызываю метод updateMaps(), который принадлежит внешнему классу. Кроме того, я вызываю в BidParser методы второго внутреннего класса InputSanityChecker.

Это плохая практика и анти-шаблон? Я создаю объект Бога здесь? (Больше функций, чтобы следовать в других внешних классах)

EDIT: У меня есть две переменные Var1, Var2 (пусть говорят), которые принадлежат Outer, но необходимы для методов updateX и checkX.

public class Outer{


    public static void main( String[] args ){
        if(args.length == 1){
            File file = new File(args[0]);
            BidParser.parseBids(file);//<--- Question refers here
        }else{
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            BidParser.parseBids(br);  //<--- and here
        }
    }


    private static void updateMaps(String[] elements){
        //.....blah blah
    }

    static class BidParser{
        public static void parseBids(File file){
            //.....blah blah
            InputSanityChecker.checkInput(elems);//<---second inner class method
            InputSanityChecker.checkMaps(elems);    //<---second inner class method
            updateMaps(elems);  //<-----outer class method

        }
        public static void parseBids(Reader reader){
            //.....blah blah
            InputSanityChecker.checkInput(elems);//<---second inner class method
            InputSanityChecker.checkMaps(elems);    //<---second inner class method
            updateMaps(elems);  //<-----outer class method

        }
      }
    static class InputSanityChecker{

        public static boolean checkInput(String[] elements){
              //.....blah blah
        }

        public static boolean checkMaps(String[] elements){
              //.....blah blah
        }   
    }
}
  • 3
    Вы не используете внутренние классы; вы просто используете классы- члены . Это потому, что вы объявили эти классы как static . внутренние классы или не static ; они являются внутренними классами, потому что у них есть ссылка на экземпляр внешнего класса, с которым они созданы.
  • 0
    Во-вторых, ваш звонок в checkInput(elems); из BidParser недействителен (выдаст ошибку компилятора). Это должен быть InputSanityChecker.checkInput(elems);
Показать ещё 2 комментария
Теги:
design
inner-classes
cyclic-reference

1 ответ

4
Лучший ответ

Это не циклическая ссылка. Все классы - внешние и вложенные статические - должны быть одинаково независимыми от компилятора. И хотя вы вызываете статические методы, ссылок на экземпляры нет.

Эта конструкция нарушает принцип единой ответственности: BidParser должен нести ответственность за синтаксические ставки и все. Т.е. этот класс должен принимать входной сигнал - даже не File, просто Reader, - и производить некоторый Bids объект, который он должен вернуться к абоненту.

Тогда ответственность абонент 1) подготовить материалы в виде любого Reader и 2) принять произведенный Bids объект и сделать что - то с ним. Reader может быть экземпляром FileReader, BufferedReader, StringReader и т.д. См. Java IO Documentation

Кроме того, этот дизайн нарушает принцип " Не повторяй сам". Вы можете увидеть дубликат кода в BidParser. Это нарушение будет исправлено автоматически, как только вы создадите класс для работы только с более абстрактным вводом.

Учитывая InputChecker, если каждый элемент проверен inpedendently из других, этот класс должен отвечать за проверку только одного проверяемого фрагмента (элемента) за раз. И должен быть обязанностью парсера перебирать элементы и при необходимости обращаться к InputChecker.

Если во внешнем классе есть некоторые переменные, которые необходимы для анализа и проверки ставок, вы должны передать их в качестве аргументов. Если неудачная проверка не может предотвратить синтаксический анализ, то лучше всего выберете контролер из парсера. Так выглядит:

try{
     Bids bids = BidParser.parse( bidsInput );
     BidChecker.check(bids, var1);
     Maps.update(bids, var2);
} catch (...){
}

Обобщить: такой дизайн плохой, потому что он вводит BidParser класса BidParser о внутренних компонентах своих клиентов, т. BidParser связь, которую следует избегать, поскольку она не тестируется и ведет к плохой ремонтопригодности. Ваш класс не должен знать о нем других клиентов, кроме переданных через аргументы. И (что является излишним в этом кратком примере) концепция инверсии управления (и последующая инъекция зависимостей) идет еще дальше в стремлении к свободному соединению и созданию более проверяемого и чистого дизайна.

Рассмотрим SOLID принципы объектно-ориентированного проектирования. Также статья Википедии " Не повторяйте сами ссылки на другие полезные принципы, которые вводят какую-то философию программирования".

  • 0
    спасибо за солидный ответ

Ещё вопросы

Сообщество Overcoder
Наверх
Меню