Статический или экземплярный метод для совместного использования

Вот что я пытаюсь определить...

У меня есть служебный класс для добавления строк в текстовый файл. Это должно использоваться рядом других классов, таких как общий файл журнала.

В моей первой реализации у меня были все классы, которые хотели использовать его, чтобы создать экземпляр без ссылки, например.

new Logger(logline,logname);

Конструктор создает PrintWriter, добавляет строку и закрывает файл.

Это казалось расточительным, поскольку для каждой добавленной строки создается новый экземпляр.

Альтернативой было использование статического метода, называемого "writeln" в этом общем классе, так как я понял, что статические методы и данные повторно используют одну и ту же память снова и снова... но

этот статический метод создает экземпляр PrintWriter для выполнения своей работы, поэтому не означает ли это, что новый экземпляр PrintWriter создается для каждой строки, например #1?

В любом случае (я относительно новичок в Java), есть ли известный, одобренный способ сделать это, или мы просто создаем и позволяем сборщику мусора убирать за нами?

Спасибо


person javaphild    schedule 24.04.2009    source источник


Ответы (3)


Разумный ответ заключается в том, что вы должны использовать «серьезный» пакет ведения журналов, такой как Commons Logging.

Однако, чтобы ответить на ваш вопрос, в этом случае вы должны использовать статический метод (если вы не хотите поддерживать экземпляры класса ведения журнала в своем коде, и в этом случае вы должны следовать другим ответам в этом потоке). Кроме того, у вас должно быть статическое поле, инициализированное, скажем, Map<String, PrintWriter>. (Вам не нужно использовать String в качестве ключа: если вам нужно конечное число типов целей ведения журнала, используйте перечисление.)

Затем, когда ваш метод увидит ключ, которого еще нет на карте, он создаст PrintWriter на месте и вставит его в карту. Вы, вероятно, захотите использовать ConcurrentHashMap в качестве типа резервной карты, чтобы он был потокобезопасным.

Вам также необходимо указать способ закрытия цели регистрации (что также удалит связанную запись с карты).

Удачи!

person Chris Jester-Young    schedule 24.04.2009
comment
Спасибо, Крис! Это было предложение, которое больше всего откликнулось во мне. Существует 2 файла журнала — один для регулярного ведения журнала и один для ошибок, поэтому хранение ссылок в HashMap (таблица отправки) — это здорово. Ключ может быть именем файла. Одного я не уловил.. Насчет закрытия цели логирования... файл закрывается после каждой строки. Мне тоже нужно освобождать память? Думал, что это происходит, когда JVM выходит (при завершении программы). - person javaphild; 24.04.2009
comment
Закрытие файла журнала для каждой строки журнала означает, что вам придется открывать его заново для каждой строки журнала. Это будет серьезный хит производительности. Вам следует рассмотреть возможность использования flush(), если цель состоит в том, чтобы убедиться, что данные журнала попадут на диск; это по-прежнему влечет за собой некоторое снижение производительности, но не так сильно. Однако, если вы по-прежнему настаиваете на закрытии файла после каждой строки, вам не нужно беспокоиться о его закрытии в другом месте. Карту можно оставить для автоматического выпуска, да. - person Chris Jester-Young; 25.04.2009
comment
Использование имени файла в качестве ключа может быть уместным, если клиенты обращаются к именам файлов только через поля строковых констант, а не как прямые строковые литералы. Это уменьшает эффект, который могут иметь опечатки, и означает, что ваши имена файлов хранятся только в одном месте, что упрощает их изменение в случае необходимости. - person Chris Jester-Young; 25.04.2009

Вы не должны выполнять какую-либо работу в своем конструкторе.

Конструкторы предназначены для настройки объекта.

Вы должны создать метод Log() для фактического ведения журнала.

Logger l = new Logger();
l.Log(logline,logname);
l.Log(logline,logname);

или вы можете настроить регистратор как синглтон.

Logger.getInstance().Log(logline, logname);

Шаблон Singleton в Java: http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html

person Chad Grant    schedule 24.04.2009

Есть несколько типов состояний, которые может захотеть сохранить этот объект, в частности PrintWriter. Если бы ваш класс Logger хранил их как данные экземпляра, то метод ведения журнала должен быть методом экземпляра, а не статическим методом. Следовательно, вам нужно отделить регистрацию от строительства:

// Pass only the PrintWriter into the constructor, not the line to be logged.
Logger myLogger = new Logger(filename);

...

// Log a message
myLogger.log("This is a message to be logged.");

// Log another message, just for kicks.
myLogger.log("this shows that myLogger can be used repeatedly.");

Я не показывал никаких подробностей реализации, но надеюсь, что этого достаточно, чтобы вы приступили к работе.

person Dan Breslau    schedule 24.04.2009