Java: дизайн с использованием синглетонов и дженериков - PullRequest
4 голосов
/ 02 марта 2009

Я использую интерфейс Predicate, который используется для просеивания через Коллекции. Например, я могу определить

public class BlackCatPredicate implements Predicate<Cat> {
  public boolean evaluate( Cat c ) {
       return c.isBlack();
  }
}

, а затем используйте некоторый служебный метод findAll( Collection<T> coll, Predicate<T> pred), чтобы применить предикат к коллекции кошек и получить только черные и т. Д.

У меня такой вопрос: я нахожу черных кошек по всему коду, поэтому нет необходимости повторять создание экземпляра BlackCatPredicate снова и снова. У него должен быть только один экземпляр. (Синглтон?) Но затем, во время написания многих предикатов, я не хочу реализовывать каждый из них как синглтон. Итак, каков здесь правильный дизайн?

Ответы [ 4 ]

12 голосов
/ 02 марта 2009

Я бы использовал константу анонимного класса и поместил бы ее в класс, с которым он работает:

public class Cat{
    public static final Predicate<Cat> BLACK_PREDICATE = new Predicate<Cat>(){
            public boolean evaluate( Cat c ) {
                return c.isBlack();
            }
        };

    // Rest of the Cat class goes here
}

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

Редактировать: Как отмечалось в комментариях, в зависимости от шаблонов использования, это может привести к более четкому коду для сбора констант предикатов (и / или фабричных методов) в отдельный класс, либо только те для кота, или все они. Это зависит в основном от их количества, насколько полезна дополнительная организация.

3 голосов
/ 02 марта 2009

Примерно так должно работать:

class Predicates
{
    private static class BlackCatPredicate implements Predicate<Cat> 
    {
        public boolean evaluate(final Cat c) 
        {
            return c.isBlack();
        }
    }

    private static final BlackCatPredicate = new BlackCatPredicate(); 


    public static Predicate<Cat> getBlackCatPredicate()
    {
        return (blackCatPredicate);
    }
}
1 голос
/ 02 марта 2009

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

Еще один более общий подход заключается в том, чтобы начать использовать библиотеку внедрения зависимостей - и выполнять все ваши создания объектов через нее. Обычно вы можете переключить тип на одиночный, при необходимости, с небольшими изменениями.

0 голосов
/ 02 марта 2009

Я бы не стал беспокоиться о создании дополнительных BlackCatPredicate экземпляров.

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

Однако это только для абстрагирования создания предиката от клиентского кода, оно не имеет ничего общего с фактическим созданием объекта. Работа с недолговечными объектами - это одна из лучших вещей, которую JVM делает лучше всего, поэтому создание нескольких дополнительных BlackCatPredicate экземпляров и немедленное их отбрасывание не повлияет ни на что.

...