Пример шаблона разработчика в Java API?

Эффективный Java Joshua Bloch описывает разработчика Pattern, который может использоваться для создания объектов с несколькими дополнительно настраиваемыми параметрами. Соглашение о присвоении имен, которое он предлагает для функций Разработчика, который "моделирует названные дополнительные параметры, как найдено в Ada и Python", кажется, не падает в соответствии со стандартным соглашением о присвоении имен Java. Функции Java имеют тенденцию полагаться на наличие глагола для запуска функции и затем основанной на существительном фразы для описания то, что это делает. Класс Разработчика только имеет название переменной, это должно быть определено той функцией.

Есть ли какие-либо API в библиотеках стандарта Java, который использует разработчика Pattern? Я хочу сравнить предложения в книге к фактической реализации в базовом наборе библиотек Java прежде, чем преследовать его использование.

13
задан Aditya W 4 July 2016 в 16:18
поделиться

3 ответа

Я не уверен насчет внутри ядра JDK, но хорошие примеры можно найти в Guava. MapMaker , наверное, лучший пример, о котором я могу подумать. Например, из документации:

ConcurrentMap<Key, Graph> graphs = new MapMaker()
    .concurrencyLevel(32)
    .softKeys()
    .weakValues()
    .expiration(30, TimeUnit.MINUTES)
    .makeComputingMap(
        new Function<Key, Graph>() {
          public Graph apply(Key key) {
            return createExpensiveGraph(key);
          }
        });

Да, такие вещи могут идти против зерна "стандартного" Java-именования, но они также могут быть очень читабельными.

Для ситуаций, когда вы не возвращаете "this", а новый объект (обычно с неизменяемыми типами), мне нравится префикс "с" - Joda Time широко использует этот паттерн. Это не шаблон конструктора, а альтернативная и связанная с ним форма построения.

17
ответ дан 1 December 2019 в 20:11
поделиться

Можно проверить значение null, а затем сохранить DBNull.Value в качестве значения. Существует статья MSDN о нулевых значениях , в которой конкретно указывается на отсутствие поддержки NULL < > наборами данных.

Там, где у вас есть

values[i] = props[i].GetValue(item, null);

сделать его

var value = props[i].GetValue(item, null);
values[i] = value ?? ((object)DBNull.Value);
-121--4950640-

Поскольку, кажется, существует много путаницы в отношении работы стековых кадров и методов, вот простая демонстрация:

static void Main(string[] args)
{
    MyClass c = new MyClass();
    c.Name = "MyTest";
    Console.ReadLine();
}

class MyClass
{
    private string name;

    void TestMethod()
    {
        StackTrace st = new StackTrace();
        StackFrame currentFrame = st.GetFrame(1);
        MethodBase method = currentFrame.GetMethod();
        Console.WriteLine(method.Name);
    }

    public string Name
    {
        get { return name; }
        set
        {
            TestMethod();
            name = value;
        }
    }
}

Результатом этой программы будет:

set _ Name

Свойства в C # являются формой синтаксического сахара. Они компилируются до методов getter и setter в IL, и возможно, что некоторые языки .NET даже не распознают их как свойства - Разрешение собственности делается полностью по конвенции, нет на самом деле никаких правил в спецификации IL.

Теперь, скажем на данный момент, у вас была действительно веская причина для программы, чтобы захотеть изучить свой собственный стек (и есть драгоценные мало практических причин для этого). Почему в мире вы хотите, чтобы он вел себя по-разному для свойств и методов?

Все обоснование атрибутов состоит в том, что они являются своего рода метаданными. Если требуется другое поведение, закодируйте его в атрибут . Если атрибут может означать две разные вещи в зависимости от того, применен ли он к методу или свойству - тогда у вас должно быть два атрибута . Установите для первого целевого объекта значение AttribureTargets.Method , а для второго - значение AttribureTargets.Property . Просто.

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

public class Customer
{
    [Required]
    public string Name { get; set; }
}

Тогда ваш код валидатора, который ничего не знает о фактически передаваемой сущности, может сделать это:

public void Validate(object o)
{
    Type t = o.GetType();
    foreach (var prop in
        t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
    {
        if (Attribute.IsDefined(prop, typeof(RequiredAttribute)))
        {
            object value = prop.GetValue(o, null);
            if (value == null)
                throw new RequiredFieldException(prop.Name);
        }
    }
}

Другими словами, вы изучаете атрибуты экземпляра , который был вам предоставлен , но который вы не обязательно знаете ничего о типе. XML-атрибуты, атрибуты контракта данных, даже атрибуты атрибутов - почти все атрибуты в .NET Framework используются таким образом для реализации некоторых функций, которые являются динамическими в отношении типа экземпляра , но не в отношении состояния программы или того, что происходит в стеке. Очень маловероятно, что вы действительно контролируете это в точке, где вы создаете трассировку стека.

Поэтому я еще раз рекомендую вам не использовать подход stack-walking, если у вас нет очень веских причин сделать это, о чем вы еще не сказали нам. В противном случае вы, вероятно, окажетесь в мире боли.

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

-121--1009586-

Он определен (не реализован) только в стандартной библиотеке, однако объекты источника данных JDBC напоминают мне о образце построителя. Создается объект источника данных, затем задается ряд свойств, а затем устанавливается соединение.

Вот пример кода...

DataSource ds = (DataSource)ctx.lookup("jdbc/AcmeDB");
ds.setServerName("my_database_server");
ds.setDescription("the data source for inventory and personnel");
Connection con = ds.getConnection("genius", "abracadabra");
0
ответ дан 1 December 2019 в 20:11
поделиться

ProcessBuilder в значительной степени является экземпляром шаблона построителя, но не совсем использует соглашения об именах Java.

 ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
 Map env = pb.environment();
 env.put("VAR1", "myValue");
 env.remove("OTHERVAR");
 env.put("VAR2", env.get("VAR1") + "suffix");
 pb.directory(new File("myDir"));
 Process p = pb.start();

В пакете SQL PreparedStatement можно рассматривать как экземпляр шаблона построителя:

 PreparedStatement stmt = conn.prepareStatement(getSql());
 stmt.setString(1, ...);
 stmt.setString(2, ...);
 ResultSet rs = stmt.executeQuery();
 ...
 stmt.setString(2, ...);
 rs = stmt.executeQuery();
 ...
1
ответ дан 1 December 2019 в 20:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: