реализация абстрактной фабрики - PullRequest
1 голос
/ 01 июля 2010

Я реализовал абстрактную фабрику вот так

public abstract class AbstractFactory {

    private static final Map FACTORIES = new HashMap();    

    AbstractFactory(FactoryType type) {
        FACTORIES.put(type, this);
    }   

    public abstract A getA();

    public abstract B getB();

    public static AbstractCatalogFactory getFactory(FactoryType type) {
        return (AbstractCatalogFactory) FACTORIES.get(type);
    }
}

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

Спасибо, Don

1 Ответ

2 голосов
/ 01 июля 2010

Об утечке this из конструктора

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

Точнее, ссылка this не должна просачивать конструктора на внешние стороны до его завершения. В противном случае внешняя сторона может в конечном итоге вызвать метод для еще не завершенного нового объекта.

У вашей реализации есть шанс, что это произойдет, поскольку this добавляется на карту, которая доступна внешним сторонам статическим методом getInstance. Средством исправления может быть синхронизация доступа к карте. Другим вариантом (как обсуждал Джош Блох в Effective Java) было бы сделать конструкторы в любом конкретном подклассе закрытыми, и вместо каждого из них в каждом подклассе использовать статический метод фабрики , чтобы добавить объект карта. Это может привести к некоторому дублированию кода.

О вашем дизайне

Очевидно, вы реализуете "каталог фабрик", а не "фабрику продуктов", так что это довольно сильно отличается от классического Abstract Factory . Без подробностей трудно сказать, оправдано ли это.

Основная проблема заключается в том, что здесь вы объединяете заводской интерфейс и заводское «хранилище», что для ИМО не очень хорошая идея. Клиенты фабрики должны видеть фабричный интерфейс только с его методами getX и не должны знать, какую конкретную фабрику они фактически используют (гораздо меньше , выбирая сами).

Более того, обычно в каждый момент времени используется только одна конкретная группа продуктов, поэтому необходим только один конкретный тип завода. Это исключает возможность смешивания несовместимых продуктов из разных семейств конкретных продуктов. Ваш текущий дизайн, кажется, позволяет это, что не является хорошим знаком для меня - но, возможно, у вас есть веская причина для этого ...

...