Property Bag

Objetivo

Agrupar um conjunto de propriedades em uma unidade lógica.

Propósito

É bastante comum que se necessite trabalhar com um conjunto de valores para diferentes propriedades normalmente como argumento para um método, como resultado de um, ou como informação de configuração de um outro objecto.

Se cada propriedade fica "livre" pelo código é mais difícil saber depois onde alterá-la ou de onde lê-la. A ideia, portanto, é usar um objeto como ponto de referência para todas as propriedades relacionadas a um certo item ou contexto. Assim, de certa forma reforçamos a tipagem de um conjunto (sacola) de propriedades sem forçar nenhuma abstração mais elaborada.

Implementação

Existem várias formas de implementar um Property Bag em java.

java.util.Map e java.util.Properties

A forma mais simples de construir um Property Bag em java é utilizando um mapa (um objeto cuja classe implemente java.util.Map ) , como por exemplo HashMap.

Esta classe já provê métodos que permitem atribuir valor a uma propriedades, listar todas as propriedades, todos os valores e todos os pares propriedade-valor. Por outro lado, o uso do mapa obriga a que todas as propriedades tenham o mesmo tipo (todas String, ou todas Color,etc…​). Isto se usarmos a tipagem forte oferecida pelo recurso de tipos genéricos. Mas caso não usemos isso, poderemos ter diferentes tipos, mas à custa de uma tipagem fraca.

// fortemente tipado, mas apenas um tipo
Map<String, Color> colors = new HashMap<>();

colors.put("Red", Color.RED);
colors.put("Blue", Color.BLUE);

Color color = colors.get("Red");
// fracamente tipado, mas mais de um tipo
Map<String, Object> colors = new HashMap<>();

colors.put("Red", Color.RED);
colors.put("Name", "John");


Color color = (Color)colors.get("Red");
String name = (String)colors.get("Name");

Embora fracamente tipado este padrão é tão útil que existe até uma classe utilitária que o implementa de uma forma mais dirigida. A classe java.util.Properties implementa um mapa de String para String e ainda possibilita persistir esse mapeamento em arquivo. Muito útil para configurações simples que podem ser convertidas de, e para, texto. O único problema é que essa conversão tem que ser feita por outro objeto que leia/escreva no objeto Properties mapeando de/para os valores corretos.

Usar um Map como suporte a Property Bag é interessante mas mais útil se as propriedades são do mesmo tipo. Na prática isto não é muito comum, excepto em ocasiões especiais como parametros de configuração, onde podemos usar a classe java.util.Properties.

Bean

Uma forma mais fortemente tipada é utilizar uma classe java comum que permita definir o tipo de cada propriedade. Esta é a forma mais comum por ser menos propensa a erro de tipagem e relativamente fácil de programar. De tão comum esta abordagem foi batizada de Bean.

Na realidade o nome "bean" (grão) deriva da diminuição de "JavaBean" (grão de Java - um trocadilho com o grão de café Java). Java Bean é uma tecnologia patenteada de componentes padronizada no pacote java.beans. A diferença principal é que um JavaBean contém um mecanismo de geração de eventos seguindo o padrão Observer que avisa quando uma propriedade é modificada e pode até delegar o controle da mudança do valor num mecanismo em que a mudança pode ser vetada.

Um "bean" tem a mesma estrutura que um JavaBean mas sem o mecanismo de eventos. Daí a ideia de que um "bean" é um Java Bean diminuido. Alguns também gostam de chamar os beans de Plain Old Java Object - POJO.

A implementação do Property Bag com um bean java estabelece uma tipagem forte para os tipos dos valores das propriedades, mas não contêm mecanismos embutidos para listar essas propriedades, valores, ou pares propriedade-valor. Isto é contra-produtivo para o uso de classes para a definição de Property Bag e por conseguinte um mecanismo que permitisse isso seria necessário.

O java inclui o pacote java.lang.reflect que permite ler os métodos e atributos de uma classe através de introspeção. Este mecanismo aliado ao pacote java.beans permite tratar uma classe como a definição de um Property Bag e qualquer objeto dessa classe como uma instância de Property Bag.

Para que estes pacotes entendam que a sua classe define um Property Bag algumas convenções devem ser seguidas (chamadas de JavaBeans naming conventions):

  1. A classe deve ter definido um construtor sem argumentos.

  2. A classe deve ter definido um método acessor e um modificador para cada propriedade, e nomeá-los corretamente. A nomenclatura consiste em prefixar o nome da propriedade com o prefixo "get" para os acessores, e o prefixo "set" para os modificadores. No caso da propriedade ter um valor logico, o prefixo do acessor deve ser "is" em vez de "get".

A convenções para JavaBeans exigem mais tipos de métodos relacionados ao controle de eventos e ao padrão Observer. Para implementar um Property Bag estes são suficientes.

Normalmente as propriedades de um Property Bag são objetos simples e não coleções de objetos (caso isso seja necessário essa coleção deverá ser encapsulada em um objeto simples), contudo nada proíbe que utilize um objeto de coleção ou array como valor de uma propriedade (propriedade multivalorada), mas o seu tratamento automático é estranho. Normalmente, ao chegar nesta situação é bom começar a desconfiar que objeto que está modelando pode não ser um Property Bag.

Discussão

O padrão Property Bag , mais conhecido pela implementação do tipo Bean no lingo java, é de uso comum e muitas vezes desapercebido sendo só evidente quando se utilizam os recursos da classe java.util.Properties.

A tecnologia de objetos é fortemente vinculada a este padrão sendo muito fácil criar um Property Bag que contenham qualquer conjunto de propriedades. E é tão comum que passa desapercebido mesmo quando a pessoa nomeia as suas classes como QualquerCoisaBean.

Outra mostra de como a tecnologia de objetos é dependente deste padrão é a tecnologia de componentes Java Bean. Esta tecnologia foi estendida por meio da Java Management Extentions (JMX) trazendo outros tipos de Propery Bags baseados em classes e interfaces. Estas tecnologias - e até os Enterprise Java Beans - embora não sendo formados apenas de Property Bag têm este padrão na sua essência.

Exemplos na API padrão

Como já vimos a classe java.util.Properties implementa o padrão Property Bag até com possibilidade de persistência em arquivo ( o famoso arquivo .properties). O JSE utiliza este padrão em System.getProperties() que retorna um objeto Properties com várias propriedades do ambiente de execução [[1]] da aplicação que permitem saber coisas interessantes como, por exemplo, o nome e a versão do sistema operacional.

Padrões associados

Property Bag pode também ser chamado de Bean, pois como vimos, essa é a essência da tecnologia Java Bean. Muitas vezes Property Bag precisam ser acessada globalmente e é útil utilizar o padrão Registry.

Objetos no padrão Transfer Object são casos particulares de Property Bag que são utilizados para transportar informação entre diferentes nodos, ou andares, da aplicação. Transfer Object é a Property Bag viajante.

Objetos no padrão Value Object podem ser entendidos como objetos no padrão Property Bag de uma propriedade só que se especializam em dar suporte à leitura e manipulação dessa propriedade sem nunca tornar acessível a objetos exteriores a sua verdadeira representação.

Scroll to Top