Когда использовать getInstanceOf вместо конструктора

Пару месяцев назад я посетил презентацию, которую устроили два представителя независимой компании по разработке программного обеспечения. В основном это касалось хорошего дизайна и практики программного обеспечения.

Эти два парня говорили в основном о Java, и я помню, как они говорили, что в некоторых случаях очень полезно использовать getInstanceOf () вместо конструктора. Это имело какое-то отношение к тому, чтобы всегда вызывать getInstanceOf () из разных классов, а не из конструктора, и как это было намного лучше для крупномасштабных проектов.

Как видите, я не могу вспомнить многое из этого сейчас: / но я помню, что аргументы, которые они использовали, были действительно убедительными. Интересно, сталкивался ли кто-нибудь из вас когда-нибудь с таким дизайном и когда, по вашему мнению, он пригодится? Или вы думаете, что это совсем не так?


person Artur    schedule 03.02.2010    source источник
comment
Я не уверен, в каком контексте вы бы это использовали. Обычным является Class.forName (org.apache.derby.jdbc.EmbeddedDriver); для загрузки драйверов db   -  person stacker    schedule 04.02.2010
comment
Не уверен, правильно ли думают другие респонденты. Вы действительно говорите об использовании фабричного метода в классе вместо прямого создания экземпляра с помощью 'new'? Или что-то другое?   -  person PSpeed    schedule 04.02.2010


Ответы (4)


Вероятно, они говорили о шаблоне статического фабричного метода (а не о методе API отражения для динамического создания объектов).

Есть несколько преимуществ такого метода, как getInstanceOf() по сравнению с конструктором и с использованием new. Статический фабричный метод может ...

  1. Выберите создание другого подкласса основного класса, если это желательно в определенных случаях (в зависимости от условий окружающей среды, таких как свойства и другие объекты / синглтоны или параметры метода).

  2. Выберите возврат существующего объекта вместо его создания. Для примера см. Boolean.valueOf (boolean) в Java API.

  3. Сделайте то же самое, что и конструктор - просто верните новый экземпляр самого класса.

  4. Предоставьте множество различных способов создания нового объекта и назовите эти методы, чтобы они были менее запутанными (например, попробуйте это с конструкторами, и вскоре у вас будет много разных перегрузок). Иногда это невозможно даже с конструкторами, если вам нужно создать экземпляр двумя разными способами, но для этого нужен только один и тот же тип параметров. Пример:

    // This class will not compile!
    public class MyClass {
        public MyClass(String name, int max) {
            //init here
        }
        public MyClass(String name, int age) {
            // init here
        }
    }
    
    // This class will compile.
    public class MyClass2 {
        private MyClass2() {
        }
        public static MyClass2 getInstanceOfMax(String name, int max) {
            MyClass2 m2 = new MyClass2();
            // init here
            return m2;
        }
        public static MyClass2 getInstanceOfAge(String name, int age) {
            MyClass2 m2 = new MyClass2();
            // init here
            return m2;
        }
    }
    
  5. Сделайте любую комбинацию из вышеперечисленного.

  6. И вдобавок ко всему, он скрывает детали создания экземпляра из других классов и поэтому может быть изменен в будущем (инкапсуляция конструкции).

Конструктор может создать новый экземпляр объекта только того типа, который запрошен. Это не может быть изменено позже.

Некоторые недостатки этого шаблона:

  1. Заводские методы статичны, поэтому не могут быть унаследованы в подклассах; родительский конструктор легко доступен для подклассов.

  2. Имена фабричных методов могут сильно различаться, и это может сбивать с толку некоторых (новых) разработчиков.

Вы также просили о личном опыте. Да, я часто использую оба шаблона. Для большинства конструкторов классов, но когда есть более сложные задачи, я использую статическую фабрику. Я также работаю над проектами на других языках (проприетарных, но похожих на Java), где эта форма построения обязательна.

person Kevin Brock    schedule 04.02.2010


Я подозреваю, что вы имеете в виду метод newInstance < / a> в классе Class. Вы можете вызвать его так: MyClass foo = MyClass.newInstance();

Эта форма создания экземпляров объекта популярна в шаблонах создания; это полезно, когда вы хотите указать конкретный тип среды выполнения объекта извне, например, в свойствах или XML-файле.

person Drew Wills    schedule 03.02.2010
comment
Однако: Class.newInstance() является злом, поскольку может генерировать проверенные исключения, которые не объявлены. Может быть лучше использовать Constructor.newInstance(), который выбрасывает InvocationTargetException. См. stackoverflow.com/questions/195321/ - person Simon Nickerson; 04.02.2010
comment
@Simon Nickerson - Это хорошая и полезная информация. Но я не уверен, что это действительно делает newInstance () «злом»; вы можете сами определить, является ли проверка исключений Java во время компиляции полезной или нет. Я сам не фанат (это ухудшает соотношение сигнал / шум в исходном коде), хотя я понимаю, что это одна из областей, в которой разумные люди не согласны. Рассмотрим Groovy: это сообщество считает тот факт, что код Groovy рассматривает частные методы как общедоступные, является функцией. - person Drew Wills; 04.02.2010
comment
Независимо от того, не согласны ли вы с проверенными исключениями Java, поведение Class.newInstance(), безусловно, удивительно. Зло, возможно, немного сильное :), но я думаю, что было ошибкой позволить ему таким образом подорвать проверенный механизм исключений. - person Simon Nickerson; 04.02.2010

Если Дрю прав, newInstance() является частью Java Reflection API. Так что это не так естественно, как использование конструктора.

Почему рекомендуется использовать его в большом проекте, может быть связано с тем, что он приводит к программированию на Java Bean style и явно делает создание объекта чем-то особенным. В большом проекте создание объекта не должно быть сквозным делом, а должно быть четко обозначенной ответственностью, часто из одного источника / завода. Но ИМХО, вы получаете все эти и многие другие преимущества с помощью шаблона IoC.

person Hubert    schedule 03.02.2010