I am wondering when should I use builder with static class inside and where classical one?
Implementation from Effective Java book
public class Pizza {
private int size;
private boolean cheese;
private boolean pepperoni;
private boolean bacon;
public static class Builder {
//required
private final int size;
//optional
private boolean cheese = false;
private boolean pepperoni = false;
private boolean bacon = false;
public Builder(int size) {
this.size = size;
}
public Builder cheese(boolean value) {
cheese = value;
return this;
}
public Builder pepperoni(boolean value) {
pepperoni = value;
return this;
}
public Builder bacon(boolean value) {
bacon = value;
return this;
}
public Pizza build() {
return new Pizza(this);
}
}
private Pizza(Builder builder) {
size = builder.size;
cheese = builder.cheese;
pepperoni = builder.pepperoni;
bacon = builder.bacon;
}
}
Regular implementation
(just diagram)
You should consider using the Builder pattern when 1. you need to prevent the object from getting into an inconsistent state AND 2. using constructor parameters would be difficult to use/read because you have an unwieldy (large) number of properties that need to be set.
Using a normal default constructor + getters/setters could allow consumers to get into an invalid/inconsistent state. I.E. They might forget to set a very important property (like Cheese), but they aren't prevented from doing so and can create a Pizza anyway, even in a "bad" state. The burden is on the consumer to set state on the object appropriately after construction.
You can normally prevent this via Constructor parameters. E.G.
private Pizza() {}
public Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon)
{
...
}
But when you have a large number of parameters this can be difficult to read/write.
So, in summary, when you want to guarantee that your object can't be constructed in an inconsistent state AND you have too many fields to set that using constructor parameters would make it difficult to use and read, you could consider using the Builder pattern.
I'd say when you are prepared to go the extra mile to make the class constructor look natural.
Who can deny that this reads like good code?
Pizza pizza = new Pizza.Builder(10).cheese(true).peperoni(true).bacon(true).build();
I mean ... isn't that just sweet? It's even got bacon!
Second (and more common) option would be:
Pizza pizza = new Pizza(10);
pizza.setCheese(true);
pizza.setPeperoni(true);
pizza.setBacon(true);
This would be easier to work with using reflection and would therefore serialise/deserialise much more easily - but suffers from a more cumbersome and verbose construction.
Third and least flexible would be:
Pizza pizza = new Pizza(10, true, true, true);
but it is possible to provide both 2nd and 3rd mechanism together which can be a plus.
How to choose
There isn't a simple way to choose. If you want to woo your customers into buying your libraries you could offer all three methods but that would then spoil one of the major the benefits of using a Builder (which is hiding the actual constructor).
I would recommend using the 2nd method and perhaps the 3rd unless there is a good reason to take the unusual route of using a Builder.
Related
I'm a Java student (relatively new) working on a game clone in Java as a side project. In the game, the player controls characters. Each character is part of a faction, and each faction has a set list of skills. The skills of one faction can not be used by any other faction. My idea for how to organize this is with nested enums, where a main Skills enum has multiple inner enums (Faction1, Faction2, etc). The idea is that I would be able to access the data for any specific skill using something along the lines of Skills.Faction1.SKILL_NAME, and to be able to access a full list of a faction's skills using Skills.Faction1.values(). A simplified example of a failed implementation of this is as follows:
public enum Skills {
FACTIONLESS_SKILL("arbitraryArgs"); //More skills than just this one
enum Faction1 {
FACTION1_FIRST_SKILL("arbitraryArgs"), //More skills between the 2
FACTION1_LAST_SKILL("arbitraryArgs");
...
}
enum Faction2 {
FACTION2_FIRST_SKILL("arbitraryArgs"), //More skills between the 2
FACTION2_LAST_SKILL("arbitraryArgs");
...
}
String arbitraryField; //1 of many fields universal among both factionless and factioned skills
Skills(String arbitraryArgs) { //1 of many universal constructors
this.arbitraryField = arbitraryArgs;
}
void doUniversalThing() {
//Code here
}
}
When I try to use this implementation, I get errors telling me that the constructors and/or fields for the values in the inner enums don't exist. I tried copy pasting the constructors and fields into each individual inner enum, however that was both unreadable and unaccommodating to potential future skills which would not be attached to a faction. This simplified example doesn't even include all of the methods and alternate constructors that must be accessible to each skill. How could I implement this idea effectively and elegantly in a way that both supports skills which are a member of a faction and skills which are not, assuming that I could implement it at all? I tried my best to explain the intended results of the code, but if anything is still unclear then just let me know. Thank you.
Edit: The contents of Faction1 were requested, so in additon to me rewriting my initial code example to maybe give a better idea of my intentions, here's a few different ways I've tried Faction1. All were either erroneous or just not ideal.
Attempt 1:
public enum Skills {
FACTIONLESS_SKILL("arbitraryArgs"); //More skills than just this one
enum Faction1 {
FACTION1_FIRST_SKILL("arbitraryArgs"), //More skills between the 2
FACTION1_LAST_SKILL("arbitraryArgs");
}
String arbitraryField; //1 of many fields universal among both factionless and factioned skills
Skills(String arbitraryArgs) { //1 of many universal constructors
this.arbitraryField = arbitraryArgs;
}
}
My first attempt was just this, which gave me an error that The constructor Skills.Faction2(String) is undefined. I understand that this is due to Faction2 being its own class and unable to use a Skills constructor, which is why I then moved to my second attempt.
Attempt 2:
public enum Skills {
FACTIONLESS_SKILL("arbitraryArgs"); //More skills than just this one
enum Faction1 {
FACTION1_FIRST_SKILL("arbitraryArgs"), //More skills between the 2
FACTION1_LAST_SKILL("arbitraryArgs");
String arbitraryField; Duplicates of Skills fields
Faction1(String arbitraryArgs) { //Duplicate of Skills constructor
this.arbitraryField = arbitraryArgs;
}
}
String arbitraryField; //1 of many fields universal among both factionless and factioned skills
Skills(String arbitraryArgs) { //1 of many universal constructors
this.arbitraryField = arbitraryArgs;
}
}
This solution technically works, in that there are no errors. However, my issue with this solution is the insane amount of code duplication this causes in my non-reduced program. Every skill has numerous fields, constructors, and methods, whether the skill is assigned to a faction or not. There are also numerous factions that would need to be made. If I ever realized that a field or method or constructor was either unneeded and should be removed or needed and should be created, I would need to create or remove it from every faction individually. This is just honestly not something I want to do on a silly side project.
I haven't thought of any other way to create these inner enums, nor have I seen any in my research, so these are my only 2 implementations so far. I hope this clears things up a bit.
A brief OOPs class to begin with --
The Faction and Skill entities seem to have a has a relationship i.e., A Factions HAS A set of Skills. Also I will create an additional enum SkillName which again has a HAS A relation ship with Skill. So keeping these in mind you could arrange you enums like so --
public enum Faction {
FACTION1(new HashMap<SkillName, Skill>(){{
put(Skill.SNIPER_SHOT.skillName(), Skill.SNIPER_SHOT);
}}),
FACTION2(new HashMap<SkillName, Skill>(){{
put(Skill.JUDGEMENT.skillName(), Skill.JUDGEMENT);
}});
Map<SkillName, Skill> skills;
Faction(Map<SkillName, Skill> skills) {
this.skills = skills;
}
public Skill[] skills(){
return this.skills.values().toArray(new Skill[0]);
}
public Skill skill(SkillName name){
Skill skill = this.skills.get(name);
if(Objects.isNull(skill)){
throw new IllegalArgumentException("Invalid Skill name");
}
return skill;
}
}
enum SkillName {
SNIPER_SHOT("SNIPER_SHOT"),
JUDGEMENT("JUDGEMENT");
String value;
SkillName(String value){
this.value = value;
}
}
enum Skill {
SNIPER_SHOT(SkillName.SNIPER_SHOT, 0, 95, 5, new boolean[] {true, true, false, false}, new boolean[] {false, true, true, true}),
JUDGEMENT(SkillName.JUDGEMENT,-25, 85, 5, new boolean[] {true, true, false, false}, new boolean[] {true, true, true, true});
SkillName name;
Integer dmg;
Integer acc;
Integer crit;
boolean[] rank;
boolean[] target;
Skill(SkillName name, Integer dmg, Integer acc, Integer crit, boolean[] rank, boolean[] target) {
this.name = name;
this.dmg = dmg;
this.acc = acc;
this.crit = crit;
this.rank = rank;
this.target = target;
}
public SkillName skillName() {
return this.name;
}
}
Now you could access the skills and a specific skill like so, --
Faction.FACTION1.skills();
Faction.FACTION2.skills();
Faction.FACTION1.skill(SkillName.SNIPER_SHOT);
Faction.FACTION1.skill(SkillName.JUDGEMENT); // this should throw exception
Faction.FACTION2.skill(SkillName.SNIPER_SHOT); // this should throw exception
Faction.FACTION2.skill(SkillName.JUDGEMENT);
The access patterns are not exactly the same as you wanted, but these work pretty much to the same extent.
SIDE NOTE -
Not sure what type of game you are developing, but in most of the games, skill of players improve (i.e. skill properties change) and players acquire new skills as well. Hence the above setup will become very rigid as enums are immutable and you will not be able to scale this. Instead, what I would suggest is that you create classes for Factions and Skills instead of enums. This way you would be able to mutate them.
Just decided to upgrade to Java 9 to use Map.of(). Thank you all for your help!
Seems like you already found your solution, but here is something that is probably much easier to use.
import java.util.Arrays;
import java.util.List;
/** Enums. https://stackoverflow.com/questions/71517372 */
public class SOQ_20220406_0201
{
/**
*
* Main method.
*
* #param args commandline arguments, should they be needed.
*
*/
public static void main(String[] args)
{
enum Faction
{
F1,
F2,
F3,
ALL,
;
}
enum Skill
{
SKILL_1(Faction.F1, "arbitraryArgs"),
SKILL_2(Faction.F2, "arbitraryArgs"),
SKILL_3(Faction.F3, "arbitraryArgs"),
SKILL_ALL_CAN_USE(Faction.ALL, "arbitraryArgs"),
;
private final Faction faction;
private final String arbitraryArgs;
Skill(Faction faction, String arbitraryArgs)
{
this.faction = faction;
this.arbitraryArgs = arbitraryArgs;
}
public static List<Skill> fetchAllSkillsForFaction(final Faction faction)
{
return
Arrays.stream(values())
.parallel()
.filter(each -> each.faction == faction)
.toList()
;
}
}
System.out.println(Skill.fetchAllSkillsForFaction(Faction.F1));
}
}
The problem is less generic, than in subj. Here I have the Builder pattern for user's convenience and a method with multiple IFs. However each IF statement is a condition on one of the object's non-final field. There're no assignment operations to these fields within the body of the method under consideration as well, as no setters provided by the class's API. Example:
public class MyFormatter {
public static class Builder {
private final boolean notOptional; // don't mind this one, just the Builder pattern
private boolean optionalA, optionalB, optionalC; // these would matter further
private Builder optionalA() { optionalA = true; return this; }
private Builder optionalB() { optionalB = true; return this; }
private Builder optionalC() { optionalC = true; return this; }
public Builder(boolean notOptional) {
this.notOptional = notOptional;
}
public MyFormatter build() {
MyFormatter formatter = new MyFormatter(notOptional);
formatter.optionalA = optionalA;
formatter.optionalB = optionalB;
formatter.optionalC = optionalC;
return formatter;
}
}
private final boolean notOptional;
private boolean optionalA, optionalB, optionalC; // Not final
private MyFormatter(boolean notOptional) {
this.notOptional = notOptional;
}
protected String publish(String msg) {
StringBuilder sb = new StringBuilder();
// Here we go: a lot of IFs, though conditions "effectively never" change
if (optionalA) {
sb.append("something");
}
if (optionalB) {
sb.append("something else");
}
if (optionalC) {
sb.append("and something else");
}
return sb.toString();
}
}
Ok, now the questions are how much JIT-compiler can do to optimize this code, and if there's anything I can do to optimize it (some lazy initialization etc.).
p.s. (Harder question) Imagine this code being translated in JavaScript (by GWT), i.e. no JVM would be involved in executing/optimizing this method. What can a programmer do in this case to improve the performance?
It is absolutely crucial for dev to see the real-time dynamics and each millisecond matter a lot.
That's it. Unless your devs can read many thousand messages per second, you're fine. The cost of
if (optionalA) {
sb.append("something");
}
consists of two parts.
The conditional branch and the appending. A mispredicted branch takes 10-20 cycles, i.e., up to 20 / 3 nanoseconds on a 3 GHz CPU. A correctly predicted branch is essentially free and because of the boolean being constant and the code being hot, you can assume that.
According to the length of "something", the appending may be more costly, but no details are given, so there's nothing to optimize.
I don't think the JIT will find something to optimize here. You could size your StringBuilder to gain a bit.
All in all, it is premature optimization.
Imagine this code being translated in JavaScript (by GWT)
Modern browsers have an advanced JIT just like Java does. Due to Javascript being weakly typed, it can't be as fast, but it comes pretty close.
Measure before optimizing, so you don't spend your time where the CPU does not.
Being fairly new to OO, I often feel I understand a concept until I try to move from a simplified example to actual requirements I am given. I'd appreciate any help understanding how to think about this particular problem.
I have a GUI which has a panel that defines a container and items that go in it. Right now, there are three types of containers. The containers have some properties (like size) and can contain one to three different types of items (two are optional). Once enough information is entered, I use the information to make a graph.
I implemented an Observer pattern. When the user enters information, it updates an observable, which notifies the graph that it has changed.
I'm happy so far. Now the wrinkles. My containers have a size, but sometimes it is entered explicitly and sometimes it is determined by what the container is holding. That is determined by the type of container. How the size is determined, if not entered explicitly, depends on whether one of the optional items is in the container. I'm not sure if the requirements writer just hates me or I am lacking enough OO experience, but those wrinkles are giving me fits. Right now, my observable just has variables to hold all the assorted information and I use a bunch of switch statements to handle the special cases.
I am thinking that I could use the builder pattern. The director would produce the data that was graphed. I would have a concrete builder for each type of container and I would instantiate the class with the container properties and the items inside it. I would have methods of the abstract builder class to return to the director the values needed for the graph, for example getContainerSize() and combine these to produce the actual data points. Also, the director could return null if the user had not yet entered enough data to complete a graph.
Am I getting close to a usable OO design? I'm not sure I didn't just bury the special casing a bit deeper.
One other wrinkle. One of the item types goes in all three containers. Right now, my observable keeps track of the container and items separately and the method that creates the graph decides what to ask for (the graph changes a lot as users play around with the values). How's that work if I have multiple builder patterns?
Maybe I am missing a step? The observable updates the builder of the current container then lets the graph know it should call the director to get its coordinates? Which would then also need to ask what the current container was?
All comments welcome that help me get my head around OO design or this problem in particular. The actual requirements have more special cases, but are variations on this basic theme.
Thanks for the replies. I think I am guilty of mixing two questions together. Here is an attempt to provide a minimal code example focusing on the Builder pattern. Note IE8 I see no identation, FireFox 8, I do- so sorry to anyone reading the code in IE8.
interface MyContainerBuilder
{
void setContents( MyContents contents );
Double myVolume();
Double myDensity();
}
class SmallContainerBuilder implements MyContainerBuilder
{
Double volume = null;
Double density = null;
MyContents contents = null;
public void setVolume()
{
if (contents != null)
{
volume = contents.myDensity() / 3.0;
}
}
public void setContents( MyContents contents )
{
this.contents = contents;
}
public Double myVolume()
{
if (volume == null)
setVolume();
return volume;
}
public Double myDensity()
{
return contents.myDensity();
}
}
class BigContainerBuilder implements MyContainerBuilder
{
Double volume = null;
Double density = null;
MyContents contents = null;
public void setVolume( Double volume )
{
this.volume = volume;
}
public void setContents( MyContents contents )
{
this.contents = contents;
}
public Double myVolume()
{
return volume;
}
public Double myDensity()
{
return contents.myDensity();
}
}
class ContainerDirector
{
Double myResult( MyContainerBuilder container )
{
return container.myVolume() * container.myDensity();
}
}
class MyContents
{
Double density;
MyContents( Double density )
{
this.density = density;
}
public Double myDensity()
{
return density;
}
}
class Test
{
public static void main(String[] args)
{
SmallContainerBuilder smallContainer = new SmallContainerBuilder();
BigContainerBuilder bigContainer = new BigContainerBuilder();
ContainerDirector director = new ContainerDirector();
//
// Assume this comes from the GUI, where an ActionListener knows which Builder
// to use based on the user's action. I'd be having my observable store this.
Double density = 15.0;
MyContents contents = new MyContents( density );
smallContainer.setContents( contents );
//
// Then I would need to tell my observer to do this.
Double results = director.myResult( smallContainer );
System.out.println( "Use this result: " + results );
}
}
I have two types of containers that use a different method to calculate the volume. So let's say I have radiobuttons to select the container type and under each radiobutton a combobox of items that can go in the selected container. The ActionListener on the combobox will put the item in the right container and save it to my observable (there are lots of other things that actually get set) and it tells my observer to use the director to get an appropriate value and the observer then updates some view component of the GUI.
My containers have a size, but sometimes it is entered explicitly and sometimes it is determined by what the container is holding. That is determined by the type of container. [...] if not entered explicitly, depends on whether one of the optional items is in the container.
Sounds like you could have different subclasses of an abstract container, each implementing getContainerSize() in a different way. One for explicitly entered, one for the case with optional item and one without it.
... and I use a bunch of switch statements to handle the special cases.
Does not sound great. Replace Conditional with Polymorphism if applicable.
I am thinking that I could use the builder pattern...
I assume that you need to determine a concrete type of object (or null) based on a set of input variables. The pattern provides a way to build a complex object if it knows what type that is, but the actual problem is to decide which type. So you need conditional code at some place. That place can be a builder but it could be simple factory as well.
Right now, my observable keeps track of the container and items separately[...] observable updates the builder of the current container[...] How's that work if I have multiple builder patterns?
Not really understanding what that Observable is observing and what changes in which case are triggering what, but Observable updating a builder (or multiple) sounds strange. That's more of a gut feeling though :)
Am I getting close to a usable OO design?
If it works, yes. But I actually can't tell you if you have created a good or usable design because I still don't know the details of your problem or your design - after reading your text several times now.
Instead of adding another page of information to your question now, try to break your problem down into smaller pieces and use code snippets / images / graphs or any type of visualization to help people understand your problem and all the connections between those pieces. Just a lot of text is rather scary and a huge OO design like that is as a whole too big and too localized for SO.
Your approach seems fine but it requires IMO quite complex Objects to justify that use.
You create a MyContents instance in your GUI via the observer. That object is then wrapped in a MyContainerBuilder which is then given to a ContainerDirector which then produces a result. That is in my opinion one step too much if MyContents or the result is simple.
Also the way you set the MyContents to the MyContainerBuilder means that you can't reuse the same concrete MyContainerBuilder instance blindly. You either have to make sure that you use it sequentially or you have to construct a new one every time.
I.e this does not work
MyContents content1 = new MyContents( 5 );
MyContents content2 = new MyContents( 6 );
smallContainer.setContents( content1 );
smallContainer.setContents( content2 ); // overwriting old state
Double results1 = director.myResult( smallContainer ); // wrong result
Double results2 = director.myResult( smallContainer );
I assume that MyContents is a generic data holding object that is filled with data in several steps by the user. Once the user is happy with it, it is submitted to be build into a result. As far as I can tell, you know at that point what the result has to be.
Below is an approach using a Strategy Pattern(? - I'm bad with all those names and little differences) which I chose to plug into the MyContents directly so the MyContents object once finalized has all details how it has to be transformed into a result. That way safes one step and you don't need to create / maintain extra builder objects. MyContents is already in a way a Builder now.
interface VolumeStrategy {
Double calculateVolume(Double density);
}
class SmallVolumeStrategy implements VolumeStrategy {
public Double calculateVolume(Double density) {
return density / 3.0;
}
}
class BigVolumeStrategy implements VolumeStrategy {
public Double calculateVolume(Double density) {
return density;
}
}
class ContainerDirector {
Double myResult( MyContents container ) {
Double density = container.myDensity();
VolumeStrategy strategy = container.myStrategy();
return density * strategy.calculateVolume(density);
}
}
class MyContents {
// built via observer
Double density;
MyContents( Double density ) {
this.density = density;
}
public Double myDensity() {
return density;
}
// plugged in at the end.
VolumeStrategy strategy;
public void setStrategy(VolumeStrategy strategy) {
this.strategy = strategy;
}
public VolumeStrategy myStrategy() {
return strategy;
}
}
public class Test {
public static void main(String[] args) {
// all those can be static
VolumeStrategy smallStrategy = new SmallVolumeStrategy();
VolumeStrategy bigStratetgy = new BigVolumeStrategy();
ContainerDirector director = new ContainerDirector();
// from the GUI
Double density = 15.0;
MyContents contents = new MyContents( density );
// building this contents ...
// ... time to submit, we know what strategy to use
contents.setStrategy(smallStrategy);
// can turn contents into result without needing to know anything about it.
Double results = director.myResult( contents );
System.out.println( "Use this result: " + results );
}
}
That's a way what I think should work well for the problem I imagine you have. I can be wrong tough.
Been a while since I used Java and was wondering if this was a decent or even correct way of setting this up.
FYI, userResults refers to a JDBI variable that isn't present in the code below.
Feel free to suggest a better method, thanks.
public class Stat
{
private int current;
private int max;
public int getCurrent() {return current;}
public void setCurrent(int current) {this.current = current;}
public int getMax() {return max;}
public void setMax(int max) {this.max = max;}
}
public class Character
{
Stat hp = new Stat();
Stat mp = new Stat();
}
Character thisCharacter = new Character();
// Set the value of current & max HP according to db data.
thisCharacter.hp.setCurrent((Integer) userResults.get("hpColumn1"));
thisCharacter.hp.setMax((Integer) userResults.get("hpColumn2"));
// Print test values
System.out.println (thisCharacter.hp.Current);
System.out.println (thisCharacter.hp.Max);
Correct? Well, does it work? Then it probably is correct.
Wether or not it is a decent way to do it then the answer is "maybe". It is hard to tell from what context this code is in. But there are some things you could keep in mind though:
In which class (or object rather) are the Stat set in? Do you feel is it the responsibility of the class to do this and know what database values to get them from? If not, consider making some kind of a class that does this.
Making chained calls such as thisCharacter.hp.setCurrent(...) is a violation of principle of least knowledge. Sometimes you can't help it, but usually it leads to kludgy code. Consider having something that handles all the logic surrounding the stats. In your code you may need a HealthStatsHandler that have methods such as loadStats(), saveStats(), and mutator actions such as takeDamage(int dmg) and revive(int health).
If you have trouble figuring things out if it has the correct object design, then study up on the SOLID principles. They provide nice guidelines that any developer should follow if they want to have code that is extensible and "clean".
This is not really a tree. It is not possible two have more than one layer of children.
Usually you define an interface let's call it Node where both Stat and Character implements it and the two children of Character would have the type Node.
I would consider creating the Stat objects seperately and passing them into Character, and making the character attributes private as follows:
public class Character
{
private Stat hp;
private Stat mp;
public Stat getHp() {return hp;}
public void setHp(Stat h) {this.hp = h;}
public Stat getMp() {return mp;}
public void setMp(Stat m) {this.mp = m;}
}
// Set the value of current & max HP according to db data.
Stat hp = new Stat();
hp.setCurrent((Integer) userResults.get("hpColumn1"));
hp.setMax((Integer) userResults.get("hpColumn2"));
Character thisCharacter = new Character();
thisCharacter.setHp(hp);
// do the same for mp
One additional simple step would be to create a Character constructor that would take an hp and an mp
What's the best practice for specifying flags in a Java method?
I've seen SWT using int as bitfields, like:
(example partially from "Effective Java, 2nd Ed." page 159):
public class Text {
public static final int STYLE_BOLD = 1 << 0; // 1
public static final int STYLE_ITALIC = 1 << 1; // 2
void printText(String text, int flags) {
}
}
and your client call looks like:
printText("hello", Text.STYLE_BOLD | Text.STYLE_ITALIC);
..but this is discouraged as you can mixed flags (int values) from different classes together without any compiler checks.
In the same book ("Effective Java"), I see the use of EnumSet, but then your user call becomes:
printText("hello", EnumSet.of(Style.Bold, Style.ITALIC));
I find this a bit verbose and I prefer the elegance of SWT.
Is there any other alternative or is this basically the two tastes you must pick?
Guess you have hit a wall. I don't see any other option. Java is verbose that's a fact. In situations like this i usually add a local variable to make the code more readable. You can do this,
EnumSet<Style> styles = EnumSet.of(Style.Bold, Style.ITALIC);
printText("hello", styles);
If you want bit style flags, Java wraps them in a BitSet. It's been around for ages, yet few people bother to use it (preferring embedding C style bit handling in ints).
The api for BitSet can be found here.
Coupled with a few well chosen static ints, it does pretty well until you start getting into checking and setting multiple bits in one pass.
I advise that you go with the EnumSet approach.
EnumSet<Style> styles = EnumSet.of(Style.Bold, Style.Italic);
This approach provides better type safety, and Style being an enum will have full-blown OO capabilities.
Late answer for anyone coming across this. Here is one way to do it to reduce memory and have a nice enum like api:
public static class MyFlag {
public static final MyFlag A = new MyFlag(1<<0);
public static final MyFlag B = new MyFlag(1<<1);
public static final MyFlag C = new MyFlag(1<<2);
public static final MyFlag ALL = A.and(B).and(C);
private final int flag;
private MyFlag(int flag){
this.flag = flag;
}
public MyFlag and(MyFlag limit){
return new MyFlag(flag & limit.flag);
}
public MyFlag not(MyFlag limit){
return new MyFlag(flag | ~limit.flag);
}
public boolean isSet(MyFlag limit){
if(limit ==null){
return false;
}
return (this.flag & limit.flag) != 0;
}
}
method:
public void doFoo(MyFlag flag){
if(MyFlag.A.isSet(flag)){
....
}
if(MyFlag.C.isSet(flag)){
....
}
}
call:
x.doFoo(MyFlag.A.and(MyFlag.C));
If you only have a limited number of methods that will be taking a set of styles (like printText, in your example), you can tweak their signature to take a variable number of Style params:
void printText(String text, Style... flags) {
EnumSet<Style> style = logicalOr(flags); // see comment below
...
}
And then your calls are very close to the untyped (int) flag route:
printText("hello", Style.BOLD, Style.ITALIC);
Sadly, there is no EnumSet.of(E... ) factory, just EnumSet.of(E first, E... more), so you'll need a generic logicalOr method to split your array into first + rest chunks. Left as an exercise to the reader =).