简体   繁体   中英

Static constructor methods in Java

I'm not really sure what to call this, because "static constructor" seems to convey the concept of static initializer blocks, but my question has to do with style.

Let's say I have a class Weapon that has your standard constructors for initializing a weapon's stats. This works fine, but sometimes I want to randomly generate a weapon. I could create a static method called FromRandom which creates a new Weapon with random stats and returns it. That way I could do something like this:

Weapon randWeapon = Weapon.FromRandom();

What's the consensus on this? Is this acceptable code?

Giving a class static methods that give you more control and gracefulness by returning instances of the class they are in is perfectly acceptable code. This is actually called the factory method pattern and is used quite often when you greater control when an instance of a class is created.

Basically, you have the static method call one of the class constructors, do whatever it needs to do in terms of logging the creation of the object, adding it to a collection, performing further operations on it, etc., and then return the created object, so the method ends up being used like a normal constructor. :D

I would prefer having multiple constructors, with parameters determining how to create the object. If there's only two options, use a boolean (you can keep the default version and chain it). If there are many, use an enum parameter.

However, I wouldn't necessarily consider your code wrong. Guava uses a similar style (see Lists ). However, note that it returns instances of another class ( List ), and itself has no constructor.

这是一种众所周知的设计模式(在某种程度上),称为抽象工厂模式,请参阅: http//en.wikipedia.org/wiki/Abstract_factory_pattern

Generally speaking, this is good and gives you some grace to the code. But I'd recommend this only for factory classes. Why? Let's consider your example

Weapon weapon = Weapon.create();

If I have a subclass of Weapon , eg Pistol with a static method similar to the previous in which you can do pass a param (bullet size for instance), then you may do

Weapon randWeapon = Pistol.create("9mm");

but you may do by mistake

Weapon randWeapon = Pistol.create();

which will not create a Pistol , but an instance of the parent class. Is this desired? Not sure. Can it be worse? Well, just think about the possibility to define create method in class Pistol as

public static Pistol create(String ... args){...}

Scaring, isn't it?

So, if one does not want to create a factory class, the solution would be to make the class final , but I generally advice people not to create final classes (think about issues with mocking).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM