M6 Posted July 27, 2006 at 09:47 AM Report #40519 Posted July 27, 2006 at 09:47 AM Ando a revisitar os Java de um ponto de vista mais evoluido e tenho (re)aprendido algumas coisas que vou aqui partilhar. Se acham que já sabem tudo sobre construtores, pois bem, ou sabem mesmo ou então estão mais ou menos enganados como eu estava antes de ler o que aqui vou colocar. 😉 Providing static factory methods instead of constructors The normal way for a class to allow a client to obtain an instance is to provide a public constructor. There is another, less widely known technique that should also be a part of every programmer's toolkit. A class can provide a public static factory method, which is simply a static method that returns an instance of the class. Here's a simple example from the class Boolean (the wrapper class for the primitive type boolean). This static factory method, which was added in the 1.4 release, translates a boolean primitive value into a Boolean object reference: public static Boolean valueOf(boolean b) { return (b ? Boolean.TRUE : Boolean.FALSE); } A class can provide its clients with static factory methods instead of, or in addition to, constructors. Providing a static factory method instead of a public constructor has both advantages and disadvantages. Advantages 1. One advantage of static factory methods is that, unlike constructors, they have names. If the parameters to a constructor do not, in and of themselves, describe the object being returned, a static factory with a well-chosen name can make a class easier to use and the resulting client code easier to read. For example, the constructor BigInteger(int, int, Random), which returns a BigInteger that is probably prime, would have been better expressed as a static factory method named BigInteger.probablePrime. (This static factory method was eventually added in the 1.4 release.) A class can have only a single constructor with a given signature. Programmers have been known to get around this restriction by providing two constructors whose parameter lists differ only in the order of their parameter types. This is a bad idea. The user of such an API will never be able to remember which constructor is which and will end up calling the wrong one by mistake. People reading code that uses these constructors will not know what the code does without referring to the class documentation. Because static factory methods have names, they do not share with constructors the restriction that a class can have only one with a given signature. In cases where a class seems to require multiple constructors with the same signature, you should consider replacing one or more constructors with static factory methods whose carefully chosen names highlight their differences. 2. A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they're invoked. This allows immutable classes to use preconstructed instances or to cache instances as they're constructed and to dispense these instances repeatedly so as to avoid creating unnecessary duplicate objects. The Boolean.valueOf(boolean) method illustrates this technique: It never creates an object. This technique can greatly improve performance if equivalent objects are requested frequently, especially if these objects are expensive to create. The ability of static factory methods to return the same object from repeated invocations can also be used to maintain strict control over what instances exist at any given time. There are two reasons to do this. First, it allows a class to guarantee that it is a singleton. Second, it allows an immutable class to ensure that no two equal instances exist: a.equals(😉 if and only if a==b. If a class makes this guarantee, then its clients can use the == operator instead of the equals(Object) method, which may result in a substantial performance improvement. The typesafe enum pattern implements this optimization, and the String.intern method implements it in a limited form. 3. A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type. This gives you great flexibility in choosing the class of the returned object. One application of this flexibility is that an API can return objects without making their classes public. Hiding implementation classes in this fashion can lead to a very compact API. This technique lends itself to interface-based frameworks, where interfaces provide natural return types for static factory methods. For example, the Collections Framework has twenty convenience implementations of its collection interfaces, providing unmodifiable collections, synchronized collections, and the like. The great majority of these implementations are exported via static factory methods in a single, noninstantiable class (java.util.Collections). The classes of the returned objects are all nonpublic. The Collections Framework API is much smaller than it would be if it had exported twenty separate public classes for the convenience implementations. It is not just the bulk of the API that is reduced, but the “conceptual weight.” The user knows that the returned object has precisely the API specified by the relevant interface, so there is no need to read additional class documentation. Furthermore, using such a static factory method mandates that the client refer to the returned object by its interface rather than by its implementation class, which is generally a good practice. Not only can the class of an object returned by a public static factory method be nonpublic, but the class can vary from invocation to invocation depending on the values of the parameters to the static factory. Any class that is a subtype of the declared return type is permissible. The class of the returned object can also vary from release to release, for enhanced software maintainability. The class of the object returned by a static factory method need not even exist at the time the class containing the static factory method is written. Such flexible static factory methods form the basis of service provider frameworks like the Java Cryptography Extension (JCE). A service provider framework is a system wherein providers make multiple implementations of an API available to users of the framework. A mechanism is provided to register these implementations, making them available for use. Clients of the framework use the API without worrying about which implementation they are using. In the JCE, the system administrator registers an implementation class by editing a wellknown Properties file, adding an entry that maps a string key to the corresponding class name. Clients use a static factory method that takes the key as a parameter. The static factory method looks up the Class object in a map initialized from the Properties file and instantiates the class using the Class.newInstance method. The following implementation sketch illustrates this technique: // Provider framework sketch public abstract class Foo { // Maps String key to corresponding Class object private static Map implementations = null; // Initializes implementations map the first time it's called private static synchronized void initMapIfNecessary() { if (implementations == null) { implementations = new HashMap(); // Load implementation class names and keys from // Properties file, translate names into Class // objects using Class.forName and store mappings. ... } } public static Foo getInstance(String key) { initMapIfNecessary(); Class c = (Class) implementations.get(key); if (c == null) return new DefaultFoo(); try { return (Foo) c.newInstance(); } catch (Exception e) { return new DefaultFoo(); } } } Disadvantages 1. The main disadvantage of static factory methods is that classes without public or protected constructors cannot be subclassed. The same is true for nonpublic classes returned by public static factories. For example, it is impossible to subclass any of the convenience implementation classes in the Collections Framework. Arguably this can be a blessing in disguise, as it encourages programmers to use composition instead of inheritance. 2. A second disadvantage of static factory methods is that they are not readily distinguishable from other static methods. They do not stand out in API documentation in the way that constructors do. Furthermore, static factory methods represent a deviation from the norm. Thus it can be difficult to figure out from the class documentation how to instantiate a class that provides static factory methods instead of constructors. This disadvantage can be reduced by adhering to standard naming conventions. These conventions are still evolving, but two names for static factory methods are becoming common: valueOf: Returns an instance that has, loosely speaking, the same value as its parameters. Static factory methods with this name are effectively type-conversion operators. getInstance: Returns an instance that is described by its parameters but cannot be said to have the same value. In the case of singletons, it returns the sole instance. This name is common in provider frameworks. In summary, static factory methods and public constructors both have their uses, and it pays to understand their relative merits. Avoid the reflex to provide constructors without first considering static factories because static factories are often more appropriate. If you've weighed the two options and nothing pushes you strongly in either direction, it's probably best to provide a constructor simply because it's the norm. 10 REM Generation 48K! 20 INPUT "URL:", A$ 30 IF A$(1 TO 4) = "HTTP" THEN PRINT "400 Bad Request": GOTO 50 40 PRINT "404 Not Found" 50 PRINT "./M6 @ Portugal a Programar."
Knitter Posted July 27, 2006 at 01:45 PM Report #40557 Posted July 27, 2006 at 01:45 PM Boas! Só uma achega 👍 Este tipo de construtores, chamemos-lhes assim, é bastante usado no Factory Pattern, um padrão de desenho muito usado no swing. E aconselho primeiro a aprenderem padrões de desenho, especialmente este, se quiserem usar o método de "Factorys" em java. Peace.
M6 Posted July 27, 2006 at 02:26 PM Author Report #40567 Posted July 27, 2006 at 02:26 PM Boas! Só uma achega 😉 Este tipo de construtores, chamemos-lhes assim, é bastante usado no Factory Pattern, um padrão de desenho muito usado no swing. E aconselho primeiro a aprenderem padrões de desenho, especialmente este, se quiserem usar o método de "Factorys" em java. Peace. Knitter, lanço-te um desafio: coloca ai um post sobre padrões, o que são, o que fazem, para que servem, como se usam... Que dizes? 👍 10 REM Generation 48K! 20 INPUT "URL:", A$ 30 IF A$(1 TO 4) = "HTTP" THEN PRINT "400 Bad Request": GOTO 50 40 PRINT "404 Not Found" 50 PRINT "./M6 @ Portugal a Programar."
Knitter Posted July 27, 2006 at 03:39 PM Report #40575 Posted July 27, 2006 at 03:39 PM Digo-te que há muito tempo que ando a "magicar" uns posts sobre o assunto, sobre esse e outros relacionados com java mas sinceramente tenho alguma apreenção sobre a minha capacidade para conseguir explicar as coisas com deve de ser 😉 Mas o maior problema é o da eterna falta de tempo. De momento estou a tentar fazer com que uma distribuição live baseada em KNOPPIX permita a autenticação na Active Directory da ESTG Leiria e isso está a matar todo o tempo livre que possuo 👍 , se alguém tiver algumas dicas sobre o assunto força! 😉 Vou ver isso entretanto, pode ser que brevemente apareçam ai uma coisinhas sobre Java, Design Patterns, Exceptions e etc. Já agora já foi colocado um tópico sobre padrões de desenho na secção de java. Aconselho todos a irem ver 🙂
M6 Posted July 27, 2006 at 03:44 PM Author Report #40576 Posted July 27, 2006 at 03:44 PM Kintter, quanto ao tempo não te posso ajudar, mas quanto aos textos, posso revê-los se quizeres. 👍 10 REM Generation 48K! 20 INPUT "URL:", A$ 30 IF A$(1 TO 4) = "HTTP" THEN PRINT "400 Bad Request": GOTO 50 40 PRINT "404 Not Found" 50 PRINT "./M6 @ Portugal a Programar."
Destineo Posted July 27, 2006 at 03:46 PM Report #40579 Posted July 27, 2006 at 03:46 PM Coloquei algo mais "basico" no Java -> Tutorias. Uns links para patterns e como funcionam. Mas estão em Inglês ... Sempre é trabalho que se pode aproveitar ... Também posso revê-los se quiseres. - Destineo
M6 Posted July 27, 2006 at 03:47 PM Author Report #40580 Posted July 27, 2006 at 03:47 PM Isso era porreiro. 👍 10 REM Generation 48K! 20 INPUT "URL:", A$ 30 IF A$(1 TO 4) = "HTTP" THEN PRINT "400 Bad Request": GOTO 50 40 PRINT "404 Not Found" 50 PRINT "./M6 @ Portugal a Programar."
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now