Как правильно реализовать интерфейс Java с внутренним классом?

У меня был блок кода, который записывал события в файл журнала:

Date rightNow = new Date();
File logfile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), ("MyLogfile" + fileSDF.format(rightNow) + ".txt"));
FileOutputStream fos;
boolean documents_directory_exists = logfile.getParentFile().exists();
boolean documents_directory_created = true;
if (!documents_directory_exists) documents_directory_created = logfile.getParentFile().mkdirs();
if (documents_directory_created){
    try {
        fos = new FileOutputStream(logfile, true);
        fos.write(new LogEntry(timestampSDF.format(rightNow), boolean01, someInt, boolean02).toString().getBytes());
        fos.close();
    } catch (IOException ioe) {
        Log.e(SomeClass.class.getName(), String.format(Locale.US, "%s %s", Constants.DEFAULT_FILE_ERROR_MESSAGE, ioe.getMessage()));
    }
} else {
        Log.e(SomeClass.class.getName(), String.format(Locale.US, "%s %s", Constants.DEFAULT_FILE_ERROR_MESSAGE, "Cannot create the necessary directories."));
}

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

public interface LogWriter {
    void writeLog(LogEntry logEntry);
}

Где находится LogEntry:

public class LogEntry{
    private String timestamp;
    private boolean booean01;
    private int someInt;
    private boolean boolean02;

    public LogEntry(timestamp, boolean01, someInt, boolean02){
        this.timestamp = timestamp;
        this.boolean01= boolean01;
        this.someInt= someInt;
        this.boolean02= boolean02;
    }

    // Getters and Setters
}

Я хочу, чтобы мой код был очень чистым, поэтому я хотел выполнять весь файловый ввод-вывод в интерфейсе, поэтому я создал внутренний класс:

public interface LogWriter {
    void writeLog(LogEntry logEntry);

    class WriteMeToTheLog {
        LogEntry logEntry;

        private static final SimpleDateFormat fileSDF = new SimpleDateFormat(Constants.ACCESS_LOGFILE_NAME_FORMAT);

        public WriteMeToTheLog(LogEntry logEntry) {
            this.logEntry = logEntry;
        }

        public void write(){
             Date rightNow = new Date();
             File logfile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), ("MyLogfile" + fileSDF.format(rightNow) + ".txt"));
             FileOutputStream fos;
             boolean documents_directory_exists = logfile.getParentFile().exists();
             boolean documents_directory_created = true;
             if (!documents_directory_exists) documents_directory_created = logfile.getParentFile().mkdirs();
             if (documents_directory_created){
                 try {
                     fos = new FileOutputStream(logfile, true);
                     fos.write(new LogEntry(timestampSDF.format(rightNow), boolean01, someInt, boolean02).toString().getBytes());
                     fos.close();
                 } catch (IOException ioe) {
                     Log.e(SomeClass.class.getName(), String.format(Locale.US, "%s %s", Constants.DEFAULT_FILE_ERROR_MESSAGE, ioe.getMessage()));
                }
            } else {
                Log.e(SomeClass.class.getName(), String.format(Locale.US, "%s %s", Constants.DEFAULT_FILE_ERROR_MESSAGE, "Cannot create the necessary directories."));
            }
        }
    }
}

Вот где я теряю ОЧЕНЬ.

В одном из классов, где у меня был исходный блок кода, я реализовал этот новый интерфейс:

public class OneOfMyClasses extends BaseClass implements LogWriter {
    public myMethod(){
        // This is where I had the original block of code
        // WHAT DO I DO HERE NOW???
    }

    @Override
    public void writeLog(){
        Date rightNow = new Date();
        writeMeToTheLog(new LogEntry(timestampSDF.format(rightNow), boolean01, someInt, boolean02).toString().getBytes());
        writeMeToTheLog.write();
    }
}

Как использовать эту новую функцию?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
49
1

Ответы 1

I want to keep my code very clean, so I wanted to do all of the file I/O within the interface, so I created an inner class

Объявление класса в интерфейсе не обязательно "чистым" .
Кроме того, это будет не внутренний класс, а статический класс, поскольку класс объявлен в интерфейсе. Все это противоречит интуиции. Класс - это реализация, а интерфейс - это API. Звучит не очень хорошо, что API декларирует структуру реализации.

Что касается вашего вопроса, я думаю, что WriteMeToTheLog (содержащий извлеченную вами логику ведения журнала) также должен реализовывать LogWriter, поскольку он выглядит как реализация LogWriter. И класс клиента должен иметь зависимость от WriteMeToTheLog, вероятно, как поле, установленное в конструкторе, хотя он все еще может реализовать LogWritter, если это имеет смысл.

Это даст:

class WriteMeToTheLog implements LogWriter { ...}

А также :

public class OneOfMyClasses extends BaseClass implements LogWriter {
    private LogWriter logWriter;

    public OneOfMyClasses (LogWriter logWriter){
       this.logWriter = logWriter;
    }

    @Override
    public void writeLog(){
        Date rightNow = new Date();       
        logWriter.write();
    }
}

Теперь вы можете создать экземпляр клиентского класса, установив зависимость:

OneOfMyClasses o = new OneOfMyClasses(new WriteMeToTheLog(new LogEntry(timestampSDF.format(rightNow), boolean01, someInt, boolean02).toString().getBytes());

Другие вопросы по теме