Шаблон Java 'Прототип' - новый против клона против класса. Новый экземпляр - PullRequest
9 голосов
/ 11 марта 2010

В моем проекте есть несколько фабрик «Прототип», которые создают экземпляры путем клонирования конечного частного экземпляра.

Автор этих фабрик говорит, что этот шаблон обеспечивает лучшую производительность, чем вызов оператора 'new'.

Используя Google, чтобы получить некоторые подсказки об этом, я не нашел ничего релевантного. Вот небольшая выдержка из javdoc из неизвестного проекта

К сожалению, clone () работает медленнее, чем звонит новый. Однако это много быстрее, чем звонить java.lang.Class.newInstance () и несколько быстрее, чем прокатить наш собственный метод "клонер".

Для меня это выглядит как старая лучшая практика времен java 1.1. Кто-то знает больше об этом? Это хорошая практика, чтобы использовать это с «современным» JVM?

Ответы [ 6 ]

22 голосов
/ 11 марта 2010

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

Я бы предложил найти несколько новых библиотек и / или новый проект для работы; -)

Прочтите эту статью класса Легенды городской производительности Java , чтобы узнать больше.

2 голосов
/ 11 марта 2010

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

Хотелось бы, чтобы у меня все еще был код, чтобы я мог поделиться им, но некоторое время назад я провел простой тест производительности этого шаблона по сравнению с использованием оператора 'new' и обнаружил, что использование оператора 'new' было, по крайней мере, в худшем случае так быстро, как этот шаблон, и в лучшем случае быстрее и эффективнее. Могут быть некоторые крайние случаи, которые мой тест не охватывал, где это могло бы все еще быть допустимым подходом, но в целом я бы сказал, избегайте этого паттерна.

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

2 голосов
/ 11 марта 2010

Gee. Это одна из худших идей, которые я когда-либо слышал.

Не делай странных вещей. Даже если вы измерили и видите какое-то явное улучшение (ну, в данном случае это нулевой шанс), подумайте долго, прежде чем делать это. Кто знает, что это будет исправлено в следующей JVM. Тогда у вас останется какой-то странный кусок кода, который работает хуже, его трудно прочитать, и некоторые ошибки из-за этого.

Я имею в виду, что люди, разрабатывающие JVM, не идиоты! Используйте new!

Я думаю, тебе следует избавиться от этого странного куска кода.

1 голос
/ 18 октября 2017

Мои тесты с DecimalFormat (OpenJDK 8 / Windows / JMH 1.19) показывают совершенно противоположное изображение:

Benchmark               Mode  Cnt     Score     Error  Units
Format.everyTimeCreate  avgt   10  9326.967 ± 199.511  us/op
Format.useClone         avgt   10  5102.397 ±  72.993  us/op
Format.useGlobalWithTL  avgt   10  4605.604 ±  59.000  us/op

Похоже, не так просто ответить, что лучше.

1 голос
/ 13 июля 2017

Я создал простой тест для класса Person. Я использую последний OpenJDK 8:

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

И получил следующие результаты:

Benchmark             Mode  Cnt     Score       Error   Units

MyBenchmark.viaClone  avgt   10     10.041 ±    0.059   ns/op
MyBenchmark.viaNew    avgt   10      7.617 ±    0.113   ns/op

Этот простой тест показывает, что создание нового объекта и установка соответствующих свойств из исходного объекта занимает на 25% меньше времени, чем его клонирование.

1 голос
/ 11 марта 2010

номер

О, мне нужно больше символов для ответа. Итак, позвольте мне расширить и сказать, что такая микрооптимизация неуместна, если нет проблем, и если есть, то вы должны быть в состоянии оценить, если это улучшит ситуацию.

...