Как сделать конструктор доступным только для класса фабрики? - PullRequest
6 голосов
/ 27 мая 2009

Хорошо, вопрос может быть не совсем ясным. Позвольте мне привести некоторые детали:

Допустим, у меня есть класс фабрики объектов Shoe (CShoe) с именем CFactory. CFactory - это одноэлементный класс, который создает и хранит все экземпляры обуви, используя простую хэш-карту Затем к статическим методам осуществляется доступ к созданным объектам.

Есть ли способ заставить конструктор CShoe так, чтобы он мог вызываться только фабрикой? (другими словами, убедитесь, что создание обуви может быть выполнено только синглтонской фабрикой обуви, а не другими классами)

Ответы [ 6 ]

5 голосов
/ 27 мая 2009

Вы можете сделать Shoe inner class из ShoeFactory:

public class ShoeFactory {

    public static class Shoe {
        private String name;

        private Shoe() {
        }

        private Shoe(String name) {
            this.name = name;
        }
    }

    public static Shoe createShoe(String shoeName) {
        return new Shoe(shoeName);
    }
}

Я думаю, что это в значительной степени охватывает все случаи, кроме .... Отражение :

public class SmellyShoe {

    public static void main(String[] args) {
        try {
            java.lang.reflect.Constructor c = Shoe.class.getDeclaredConstructors()[0];
            c.setAccessible(true);
            Shoe smelly = (Shoe)c.newInstance(null);
            // grr
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
4 голосов
/ 27 мая 2009

Вы можете предоставить доступ к пакету конструктора CShoe и поместить CShoe и CFactory в один пакет.

1 голос
/ 27 мая 2009

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

Просто используйте метод static, чтобы вернуть фабрику.

public final class Shoe implements Footwear {
    private static final FootwearFactory<Shoe,Something> FACTORY =
        new FootwearFactory<Shoe,Something>() {
            ...
            public Shoe get(Something value) {
                value = new Something(value);
                ...
                return new Show(value);
            }
        };
    private static FootwearFactory<Shoe,Something> getFactory() {
        return FACTORY;
    }

    private final Something value;
    private Shoe(Something value) {
        this.value = value;
    }
    ...
}
1 голос
/ 27 мая 2009

Поскольку вы хотите добавить каждый объект на карту, вы также можете переместить эту логику в конструктор CShoe - объект добавит себя сам.

0 голосов
/ 27 мая 2009

Не могли бы вы просто передать экземпляр вызывающей стороны в качестве аргумента статического члена shoe и выполнить проверку наподобие "isInstanceOf", которая вызывает конструктор, если true?

0 голосов
/ 27 мая 2009

Вы могли бы передать фабричный объект в конструктор?

public CShoe(CFactory factory)
{
    if (factory == null ||
          !factory.isValid()) // or whatever
    {
        throw new IllegalArgumentException();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...