Предположим начальный сценарий, следуя которому я был бы модифицированным проблемным случаем.
interface Logger {
log() { }
}
class LogFile extends Logger {
log() { // log to file }
}
class LogDB extends Logger {
log() { // insert log into DB }
}
Теперь LogDB меняется на что-то вроде:
class LogDB {
logMySQL() { };
logMongo() { };
}
Как это изменение можно включить в LogDB, хотя я все еще хочу, чтобы оно соответствовало интерфейсу Logger?
3 ответа
Если LogDB
необходимо реализовать Log
, но при этом необходимо также вести индивидуальное ведение журнала, добавьте функцию, которая выполняет общие действия регистрации в соответствии с требованиями интерфейса, и вызывает ее из каждой настроенной версии (или наоборот). наоборот, в зависимости от ваших потребностей):
public void log() {
//Common logging stuff here
}
public void logDB() {
//Database-specific logging here...
log();
}
public void logMongo() {
//Mongo-specific logging here...
log();
}
Но, как заявил @kocko, вы, похоже, смешиваете два типа входа в один объект, поэтому вы в первую очередь задаете вопрос. Разделите его, как он предлагает, тогда у вас не будет этой проблемы с самого начала.
Я думаю, что лучше создать два подкласса класса LogDB
- один для работы с MongoDB и один для MySQL.
class LogMongoDB extends LogDB {
@Override
log() {
//persist the log in MongoDB
}
}
class LogMySQL extends LogDB {
@Override
log() {
//persist the log in MySQL
}
}
Я бы поступил иначе, не с наследованием , а с составом .
interface Logger {
log(String message) { }
}
class LogFile extends Logger {
public LogFile(File file) {}
log(String message) { /* log to file */ }
}
class LogDB extends Logger {
private DBLogConf dbConf;
private DBAbstractionLayer dbal;
public LogDB(IDBLogConf dbConf, IDBAbstractionLayer dbal) {
this.dbConf = dbConf;
this.dbal = dbal;
}
log(String message) {
List<String> fields = new ArrayList<String>();
fields.add(dbConf.getLogField());
List<String> values = new ArrayList<String>();
fields.add(message);
dbal.insert(dbConf.getContainer(), fields, values);
}
}
interface IDBLogConf {
public String getContainer(); // table or document
public String getLogField();
}
class DBLogConf implements IDBLogConf { /* ... */ }
interface IDBAbstractionLayer {
public void insert(String container, List<String> fields, List<String> values) {
// ...
}
// other methods
}
class JDBCAbstractionLayer implements IDBAbstractionLayer {
private Connection conn;
public JDBCAbstractionLayer(Connection conn) {
this.conn = conn;
}
public function insert(...) { /* ... */}
}
abstract class NoSQLAbstractionLayer implements IDBAbstractionLayer {
// ...
}
class MongoAbstractionLayer extends NoSQLAbstractionLayer {
// ...
}
Собираем все вместе:
IDBConf dbConf = new DBConf('log_table', 'details');
IDBAbstractionLayer dbal = new JDBCAbstractionLayer(/* some JDBC connection, */);
Logger dbLogger = new LogDb(dbConf, dbal);
dbLogger.log("Something");
Logger fileLlogger = new LogFile(new File('/var/log/my_log'));
fileLogger.log("Something");
Однако это кажется более сложным, чем приведенные выше примеры, эта реализация не нарушает SRP и позволяет избежать дублирования кода.
Похожие вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.