Абстрактный Дизайн Фабрика Ява


Я новичок на выполнение Дизайн-Шаблон и хотели бы сильно укрепить свои знания, чтобы стать хорошим программистом, как я могу. Это правильная реализация абстрактного дизайн-завод? Идея здесь заключается в том, что я могу использовать как синонимы либо ConsoleLogger или журнала для трех различных "уровнях" лесозаготовки (выполнения, вывода и ошибок). Я хочу, чтобы клиент мог входить оформление и вывод на консоль, но ошибки записывает в файл, если надо.

Интерфейс Регистратора:

public interface ILogger {
    public void log(String content);
}

База Лесозаготовки Фабрика:

import java.util.HashMap;

public abstract class LoggingFactory {
    static {
        factoryMap = new HashMap<String, LoggingFactory>();
    }

    private static HashMap<String, LoggingFactory> factoryMap;

    public abstract ILogger getLogger();

    public static void register(String type, LoggingFactory factory) {
        factoryMap.put(type, factory);
    }

    public static LoggingFactory getFactory(String type) {
        return factoryMap.get(type);
    }
}

ConsoleOutputLoggingFactory:

public class ConsoleOutputLoggingFactory extends LoggingFactory {
    static {
        LoggingFactory.register("ConsoleOutputLoggingFactory", new ConsoleOutputLoggingFactory());
    }

    @Override
    public ILogger getLogger() {
        return new ConsoleOutputLogger();
    }
}

ConsoleOutputLogger:

public class ConsoleOutputLoggerimplements ILogger {
    @Override
    public void log(String content) {
        System.out.println("ConsoleOutputLogger " + content);
    }
}

FileOutputLoggingFactory:

public class FileOutputLoggingFactory extends LoggingFactory {
    static {
        LoggingFactory.register("FileOutputLoggingFactory", new FileOutputLoggingFactory());
    }

    @Override
    public ILogger getLogger() {
        return new FileOutputLogger();
    }
}

FileOutputLogger:

public class FileOutputLogger implements ILogger {
    @Override
    public void log(String content) {
        //write output to file
    }
}

ConsoleErrorLoggingFactory:

public class ConsoleErrorLoggingFactory extends LoggingFactory {
    static {
        LoggingFactory.register("ConsoleErrorLoggingFactory", new ConsoleErrorLoggingFactory());
    }

    @Override
    public ILogger getLogger() {
        return new ConsoleErrorLogger();
    }
}

ConsoleErrorLogger:

public class ConsoleErrorLogger implements ILogger {
    @Override
    public void log(String content) {
        System.out.println("ConsoleErrorLogger" + content);
    }
}

FileErrorLoggingFactory:

public class FileErrorLoggingFactory extends LoggingFactory {
    static {
        LoggingFactory.register("FileErrorLoggingFactory", new FileErrorLoggingFactory());
    }

    @Override
    public ILogger getLogger() {
        return new FileErrorLogger();
    }
}

FileErrorLogger:

public class FileErrorLogger implements ILogger {
    @Override
    public void log(String content) {
        //write error to file
    }
}

Инициализатор Фабрика:

public class LoggingInitializer {
    public LoggingInitializer() {
        LoggingFactory.register("ConsoleOutputLogger", new ConsoleOutputLoggingFactory());
        LoggingFactory.register("FileOutputLogger", new FileOutputLoggingFactory());
        LoggingFactory.register("ConsoleErrorLogger", new ConsoleErrorLoggingFactory());
        LoggingFactory.register("FileErrorLogger", new FileErrorLoggingFactory());
    }
}

Главная:

public class AbstractFactoryExample {
    public static void main(String[] args) {
        new LoggingInitializer();

        ILogger outputLogger = LoggingFactory.getFactory("OutputLogger").getLogger();
        if (outputLogger != null)
            outputLogger.log("Hello World");
    }
}


119
0
задан 8 февраля 2018 в 06:02 Источник Поделиться
Комментарии
1 ответ


static {
factoryMap = new HashMap<String, LoggingFactory>();
}

private static HashMap<String, LoggingFactory> factoryMap;


можно упростить следующим без каких-либо изменений в функциональности:

private static final Map<String, LoggingFactory> factoryMap = new HashMap<>();



public class LoggingInitializer {
public LoggingInitializer() {
LoggingFactory.register("ConsoleOutputLogger", new ConsoleOutputLoggingFactory());
LoggingFactory.register("FileOutputLogger", new FileOutputLoggingFactory());
LoggingFactory.register("ConsoleErrorLogger", new ConsoleErrorLoggingFactory());
LoggingFactory.register("FileErrorLogger", new FileErrorLoggingFactory());
}
}

Инициализация класса происходит только в его инициализатор блоков. Нигде.
Что ты делаешь здесь является подключение зависимостей. Использовать Ди рамок, что ...

Если вы собираетесь настроить заводов таким образом, в первую очередь, вы могли просто не иметь их зарегистрировать сами. Странно, что они регистрируют себя в любом случае. Что приводит к следующим изменениям:


  1. LoggerFactory реализации не должны быть получены от LoggingFactory чтобы иметь доступ к factoryMapтолько чтобы соответствовать getLogger интерфейс.

  2. На самом деле getLogger интерфейс-это то, что вы бы в функциональный интерфейс в современных Java.

В результате упрощений для вашего API. Вместо того, чтобы четко строить заводы и используя getFactoryты гораздо лучше скрывает реализацию деталь заводов и вместо использования фасада, например, так:

public static final class LoggingFactory {
private static final Map<String, Supplier<ILogger>> factoryMap = new HashMap<>();
static {
ILogger consoleOutLoggerSingleton = new ConsoleOutputLogger();
factoryMap.put("ConsoleOutputLogger", () -> consoleOutputLoggerSingleton);

ILogger fileOutputLoggerSingleton = new FileOutputLogger();
factoryMap.put("FileOutputLogger", () -> fileOutputLoggerSingleton);

ILogger consoleErrorLoggerSingleton = new ConsoleErrorLogger();
factoryMap.put("ConsoleErrorLogger", () -> consoleErrorLoggerSingleton);

ILogger fileErrorLoggerSingleton = new FileErrorLogger();
factoryMap.put("FileErrorLogger", () -> fileErrorLoggerSingleton);
}

public static ILogger getLoggerFor(String name) {
return factoryMap.getOrDefault(name, () -> new NoOpLogger()).get();
}
}

Это отсекает "человек посередине" вашей фабрики, не говоря уже о инициализации за пределами класса. Оно также является более в соответствии с обычным API журналирования Java, где вы непосредственно получить регистратор.

В заключение вы должны понимать, что изобретать рубки, обычно "плохая идея™". Если это не префикс, я бы помыл голову за это :)

Наконец: просто потому, что там находится фабрика, клиент вам API не нужно знать,- как правило, менее косвенности свой API, тем легче ее будет использовать. Стремиться свести к минимуму способы с помощью вашего API.

1
ответ дан 9 февраля 2018 в 01:02 Источник Поделиться