Skipping superfluous verification with immutable flyweights - java

I have an immutable class that looks something like this:
final class Foo {
private final String name;
private final MutableObject mo;
public Foo(String name, MutableObject mo) {
mo = mo.clone();
if(!Foo.testValidity(mo)) // this test is very expensive
throw new IllegalArgumentException();
this.name = name;
this.mo = mo;
}
public Foo bar(Foo that) {
return new Foo(this.name, that.mo);
}
}
The bar method returns a Foo object by mixing the internals of two existing Foo objects. Because the MutableObject is already in a Foo object, it is guaranteed to be valid and doesn't need copying or verification (which the constructor currently does).
Because the verification (and possibly the clone?) are expensive, I'd like to avoid them if possible. What's the best way to do this? This is was what I came up with:
final class Foo {
private final String name;
private final MutableObject mo;
public Foo(String name, MutableObject mo) {
this(name, mo, VerificationStyle.STRICT);
}
private Foo(String name, MutableObject mo, VerificationStyle vs) {
if(vs == VerificationStyle.STRICT) {
mo = mo.clone();
if(!Foo.testValidity(mo)) // this test is very expensive
throw new IllegalArgumentException();
}
this.name = name;
this.mo = mo;
}
public Foo bar(Foo that) {
return new Foo(this.name, that.mo, VerificationStyle.LENIENT);
}
private static enum VerificationStyle { STRICT, LENIENT; }
}
I thought that, at least, it would be cleaner/clearer than using a dummy parameter and less error prone than swapping the order, but is there a better way to do this? How would this normally be accomplished?

Maybe hide the constructor altogether and create new instances using a factory-like method, e.g.:
private Foo(String name, MutableObject mo) {
this.name = name;
this.mo = mo;
}
public Foo bar(Foo that) {
return new Foo(this.name, that.mo);
}
public static Foo create(String name, MutableObject mo) {
mo = mo.clone();
if(!Foo.testValidity(mo)) // this test is very expensive
throw new IllegalArgumentException();
return new Foo(name, mo);
}

Related

Is it correct to have static factory method to get a new instance with one field updated?

I think the title is self-descriptive but I will give an example to elaborate on my question. I have a DTO class with few fields (a CarDataTransferObj class in my example). In another class (let's call it class A) I need to create a new instance of that object few times, but with only one field updated (length field in my example). Given DTO must be immutable in class A. As there is "many" fields in the class CarDataTransferObj, I thought about following approach (to avoid repeating code in class A):
#Builder
public class CarDataTransferObj {
private Integer id;
private String color;
private String manufacturer;
private String model;
private String uniqueIdNr;
private Integer nrOfDoors;
private EngineType engineType;
private Integer length;
private Integer safetyLevel;
public static CarDataTransferObj newInstanceWithUpdatedLength(final CarDataTransferObj car, final Integer newLength) {
return CarDataTransferObj.builder()
.id(car.getId())
.color(car.getColor())
.manufacturer(car.getManufacturer())
.model(car.getModel())
.uniqueIdNr(car.getUniqueIdNr())
.nrOfDoors(car.getNrOfDoors())
.engineType(car.getEngineType())
.length(newLength)
.safetyLevel(car.getSafetyLevel())
.build();
}
}
For me it smells like a little anti-pattern usage of static factory methods. I am not sure whether it's acceptable or not, hence the question.
Is using static factory method in the presented way an anti-pattern, and should be avoided ?
In my searching, I didn't come across anyone calling this1 an anti-pattern.
However, it is clear that if you try to do this using a classic builder that is not specifically implemented to support this mode of operation .... it won't work. For instance, the example CarBuilderImpl in the Wikipedia article on the Builder design pattern puts the state into an eagerly created Car instance. The build() method simply returns that object. If you tried to reuse that builder in the way that you propose, you would end up modifying a Car that has already been built.
There is another problem you would need to worry about. In we modified the Wikipedia CarBuilder example to add actual wheels (rather than a number of wheels) to the Car being built, we have to worry about creating cars that share the same wheels.
You could address these things in a builder implementation, but it is unclear whether the benefits out-weigh the costs.
If you then transfer this thinking to doing this using a factory method, you come to a slightly different conclusion.
If you are doing this as a "one-off", that's probably OK. You have a specific need, the code is clunky ... but so is the problem.
If you needed to do this for lots of different parameters, or combinations of parameters, this is not going to scale.
If the objects that are created are mutable, then this approach is could be problematic in a multi-threaded environment depending on how you control access to the objects you are using as templates.
1 - There are no clear measurable criteria for whether something is an anti-pattern or not. It is a matter of opinion. Admittedly, for many anti-patterns, there will be wide-scale agreement on that opinion.
It seems a little inefficient to construct an entirely new instance via a builder every time you want to make a new copy with a small modification. More significantly, it sounds like the places where you need the class to be immutable are isolated to places like class A. Why not try something like this:
public interface ICarDataTransferObject {
public Integer GetId();
public String GetColor();
public String GetManufacturer();
public String GetModel();
public String GetUUID();
public Integer GetDoorCount();
public EngineType GetEngineType();
public Integer GetLength();
public Integer GetSafteyLevel();
}
public class CarDataTransferObject Implements ICarDataTransferObject {
private Integer _id;
private String _color;
private String _manufacturer;
private String _model;
private String _uniqueIdNr;
private Integer _nrOfDoors;
private EngineType _engineType;
private Integer _length;
private Integer _safetyLevel;
public Integer GetId() { return _id; }
public void SetId(Integer id) { _id = id; }
public String GetColor() { return _color; }
public void SetColor(String color) { _color = color; }
public String GetManufacturer() { return _manufacturer; }
public void SetManufacturer(String manufacturer) { _manufacturer = manufacturer; }
public String GetModel() { return _model; }
public void SetModel(String model) { _model = model; }
public String GetUUID() { return _uniqueIdNr; }
public void SetUUID(String uuid) { _uniqueIdNr = uuid; }
public Integer GetDoorCount() { return _nrOfDoors; }
public void SetDoorCount(Integer count) { _nrOfDoors = count; }
public EngineType GetEngineType() { return _engineType; }
public void SetEngineType(EngineType et) { _engineType = et; }
public Integer GetLength() { return _length; }
public void SetLength(Integer length) { _length = length; }
public Integer GetSafteyLevel() { return _safetyLevel; }
public void SetSafteyLevel(Integer level) { _safteyLevel = level; }
public CarDataTransferObject() {}
public CarDataTransferObject(ICarDataTransferObject other) { ... }
public ReadOnlyCarDataTransferObject AsReadOnly() {
return ReadOnlyCarDataTransferObject (this);
}
}
}
public class ReadOnlyCarDataTransferObject Implements ICarDataTransferObject {
private ICarDataTransferObject _dto = null;
public Integer GetId() { return _dto.GetId(); }
public String GetColor() { return _dto.GetColor(); }
public String GetManufacturer() { return _dto.GetManufacturer(); }
public String GetModel() { return _dto.GetModel(); }
public String GetUUID() { return _dto.GetUUID(); }
public Integer GetDoorCount() { return _dto.GetDoorCount(); }
public EngineType GetEngineType() { return _dto.GetEngineType(); }
public Integer GetLength() { return _dto.GetLength(); }
public Integer GetSafteyLevel() { return _dto.GetSafteyLevel; }
public ReadOnlyCarDataTransferObject (ICarDataTransferObject other) {
_dto = other;
}
}
Now when you want class A to have a copy no one can modify, just use the copy constructor and only expose a ReadOnly version of that copy.
public class A {
ICarDataTransferObject _dto;
ReadOnlyCarDataTransferObject _readOnlyDTO;
public ICarDataTransferObject GetDTO() { return _readOnlyDTO; }
public A(ICarDataTransferObject dto) {
_dto = new CarDataTransferObject(dto);
_readOnlyDTO = new ReadOnlyCarDataTransferObject(_dto);
}
}
You commonly see this approach in .NET applications.
While it is debatable whether your static method is an anti-pattern or not, it surely won't scale for combinations of different attributes. Nonetheless, even if it's not an anti-pattern, I think there is a better way to accomplish what you need.
There's a variant of the traditional builder pattern that, instead of creating a new empty builder, accepts an already built object and creates an already initialized builder. Once you create the builder this way, you simply change the length attribute in the builder. Finally, build the object. In plain code (no Lombok, sorry) it could be like this:
public class CarDataTransferObj {
private Integer id;
private String color;
// other attributes omitted for brevity
private Integer length;
// Private constructor for builder
private CarDataTransferObj(Builder builder) {
this.id = builder.id;
this.color = builder.color;
this.length = builder.length;
}
// Traditional factory method to create and return builder
public static Builder builder() {
return new Builder();
}
// Factory method to create and return builder initialized from an instance
public static Builder builder(CarDataTransferObj car) {
Builder builder = builder();
builder.id = car.id;
builder.color = car.color;
builder.length = car.length;
return builder;
}
// getters
public static class Builder {
private Integer id;
private String color;
private Integer length;
private Builder() { }
public Builder withId(Integer id) { this.id = id; return this; }
public Builder withColor(String color) { this.color = color; return this; }
public Builder withLength(Integer length) { this.length = length; return this; }
public CarDataTransferObj build() {
return new CarDataTransferObj(this);
}
}
}
Now with all this infrastructure in place, you can do what you want as easy as:
CarDataTransferObj originalCar = ... // get the original car from somewhere
CarDataTransferObj newCar = CarDataTransferObj.builder(originalCar)
.withLength(newLength)
.build();
This approach has the advantage that it scales well (it can be used to change any combination of parameters). Maybe all this builder's code seems boilerplate, but I use an IntelliJ plugin to create the builder with two keystrokes (including the variant factory method that accepts a built instance to create an initialized builder).
I'm still new to java but..
I guess making a copy method which takes the CarDataTransferObj object variables and sets their values to another CarDataTransferObj object variables and changing the the length using it's setter method would be better idea
Example:
public class CarDataTransferObj {
private Integer id;
private String color;
private String manufacturer;
private String model;
private String uniqueIdNr;
private Integer nrOfDoors;
private EngineType engineType;
private Integer length;
private Integer safetyLevel;
public void Copy(CarDataTransferObj copy) { //Could add another parameter here to be the new length
copy.setId(id);
copy.set(color);
copy.setManufacturer(manufacturer);
copy.setModel(model);
copy.setUniqueIdNr(uniqueIdNr));
copy.setNrOfDoors(nrOfDoors));
copy.setEngineType(engineType));
copy.setLength(length);
copy.setSafetyLevel(safetyLevel));
}
}
public class SomeOtherClass {
CarDataTransferObj car1 = new CarDataTransferObj(); //Using this way made you able to use the constructor for a more useful thing
//You set the variables you want for car1 here
CarDataTransferObj car2 = new CarDataTransferObj();
car1.Copy(car2)
car2.setLength(newLength) //Set the new length here
}

Using Non-Static Methods as Enum Properties with Generics

I'll try to keep this short. I'm trying to do something like this:
public enum Fruit {
APPLE("Apple", appleHelper::doAppleThing),
ORANGE("Orange", orangeHelper::doOrangeThing);
private String name;
private Function<String, List<T>> fruitFunction;
Fruit(String name, Function<String, List<T>> fruitFunction) {
this.name = name;
this.fruitFunction = fruitFunction;
}
public String getName() {
return name;
}
public <T> List<T> applyFruitFunction(String someString) {
return fruitFunction.apply(someString);
}
}
Such that later, I can have a method like
private <T> List<T> doFruitThing(String someString, Fruit fruit) {
List<T> transformedFruits = fruit.applyFruitFunction(someString);
if (transformedFruits.isEmpty()) {
throw new FruitException("There was no fruit of type " + fruit.getName());
}
return transformedFruits;
}
There's two problems I'm running into here.
doAppleThing and doOrangeThing are not static methods, and ideally will stay that way, and I can't find any way of creating a local instance of appleHelper and orangeHelper to make the method reference work.
Even if I were to make the methods static, enums can't have Type parameters, so there's no way to have Function<String, List<T>> fruitFunction as a field.
Is there a way this can be done? Or a better approach to this?
Enum values can have their own method implementations. So I would write this as:
public enum Fruit {
APPLE("Apple") {
private final AppleHelper helper = new AppleHelper();
#Override
public <T> List<T> applyFruitFunction(String someString) {
return helper.doAppleThing(someString);
}
},
ORANGE("Orange") {
private final OrangeHelper helper = new OrangeHelper();
#Override
public <T> List<T> applyFruitFunction(String someString) {
return helper.doOrangeThing(someString);
}
};
private String name;
Fruit(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract <T> List<T> applyFruitFunction(String someString);
}
However, if you get to the point of needing per-instance state for enum instances, the thing you have is less and less an enum and more of just an abstract base class. It might be better to look into a more OO approach, using a factory/flywheel pattern for example, rather than being tied to a pure enum for this sort of thing. (It's hard to tell for sure because the code in the question is obviously just a simplified example.)

Runtime exception during retrieval of object

public static void main(String args[])
{
List a =new ArrayList<Object>();
a.add("asha");
a.add("saha");
ArrayList<SampleObject> sampleObjects =(ArrayList<SampleObject>)a;//Yes this should not be done but still
sampleObjects.get(0).getName();// exception is thrown here
}
And the class is
public class SampleObject implements Serializable
{
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getNumber()
{
return number;
}
public void setNumber(String number)
{
this.number = number;
}
private String name;
private String number;
}
Can someone please explain why is this runtime exception.
How was the data inserted in sampleObjects when the types itself doesnot match?
When you make a cast, you're assuming the responsibility for the object you cast (on this case String) to be of the type you're casting to (on this case SampleObject). Later, at runtime, the JVM discovers you didn't fulfill that responsibility (a String is not a SampleObject) and complains with a RuntimeException (more precisely a ClassCastException).
The exception says you cannot cast String objects to SampleObject type. For a proper retrieval of name properties try this;
SampleObject s1 = new SampleObject();
s1.setName("asha");
SampleObject s2 = new SampleObject();
s1.setName("saha");
ArrayList<SampleObject> sampleObjects = new ArrayList<>();
sampleObjects.add(s1);
sampleObjects.add(s2);
System.out.println(sampleObjects.get(0).getName());

Good way to organize group of constants in enum-like fashion

I'm trying to find a good way to orginize a group of constant values that are used simply for immutable data.
Here is what I'm currently attempting:
public class FishType {
//PredatorFishType extends FishType
public static final PredatorFishType SHARK = new PredatorFishType(5, 20, "Shark");
public static final FishType CAT_FISH = new FishType("Cat Fish");
private String name;
private FishType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
I use reflection to gather the final values into a collection aswell. I used to utilize enum but was forced to think of a new way to do this when different types of fish came into play such as the predator which contains other data such as food and so on. These constants are only used for data displaying purposes and have no reason to be mutated.
If there is some way to have multiple enum types within the same enum (If that makes any sense at all), that'd be great.
Thanks for reading.
You can either use constructor overloading or a combination of overloading and a wrapper class. If you know for certain that this data is immutable and will always be that way, I don't see anything wrong with sticking to enums for it. For the sake of putting it into one class, I've included the enums in the EnumTester class, but you may not want to do that.
Here's an example that prints "Cat Fish 5 20 Shark" and "Cow Fish" when run, using nothing but enums and a wrapper class. You could put accessors wherever you need them, depending on what you actually want to do with the information - I'm trying to demonstrate how to compose the two enums, not how to use them.
package enums;
public class EnumTester
{
public enum MainType {
CAT_FISH("Cat Fish"), DOG_FISH("Dog Fish"), COW_FISH("Cow Fish"); //everything has a name...
private String name;
private MainType(String name){
this.name = name;
}
public String getTypeDetails(){
return name;
}
}
public enum SubType {
PREDATOR(5, 20, "Shark"), PREY(), MANATEE(); //but not everything has any additional information
private boolean isFullSubType;
private int val1;
private int val2;
private String subName;
private SubType(int val1, int val2, String subName){
this.isFullSubType = true;
this.val1 = val1;
this.val2 = val2;
this.subName = subName;
}
private SubType(){
this.isFullSubType = false;
this.val1 = -1;
this.val2 = -1;
this.subName = "none";
}
public String getSubTypeDetails()
{
if( isFullSubType ) {
return val1 + " " + val2 + " " + subName;
}
else {
return "";
}
}
}
private MainType mainType;
private SubType subType;
public EnumTester(MainType mainType, SubType subType)
{
this.mainType = mainType;
this.subType = subType;
}
public static void main(String[] args)
{
EnumTester kittyShark = new EnumTester(MainType.CAT_FISH, SubType.PREDATOR);
System.out.println(kittyShark.printDetails());
EnumTester cowManatee = new EnumTester(MainType.COW_FISH, SubType.MANATEE);
System.out.println(cowManatee.printDetails());
}
public String printDetails(){
return mainType.getTypeDetails()+" "+subType.getSubTypeDetails();
}
}
I typically follow a similar pattern to what you've done above. I might make the class FishTypes to be the collector, just to keep the FishType interface a bit cleaner. You can also invent some syntactic sugar to help you collect registered FishTypes:
public static final Set<FishType> registeredFish = new HashSet<>();
public static final PredatorFishType SHARK = register(new PredatorFishType(5, 20, "Shark"));
public static final FishType CAT_FISH = register(new FishType("Cat Fish"));
public static <T extends FishType> T register(T fishType) {
registeredFish.add(fishType);
return fishType;
}

Why Java Method Reference of instance method cannot be assigned to Consumer interface

Here is my Code :
public class SearchByLambda {
private Map<String,Consumer<Person>> searchCritertiaHolder = new HashMap<String,Consumer<Person>>();
private static final String AGED = "aged";
public SearchByLambda(){
searchCritertiaHolder.put(AGED, (Person p)-> {p.filterAgedPerson(p);} );
}
private Consumer<Person> getFilter(String personType){
return searchCritertiaHolder.get(personType);
}
public static void main(String[] args) {
SearchByLambda searchUsage = new SearchByLambda();
Person p = new Person(59,"shailesh");
Person p1 = new Person(58,"ganesh");
searchUsage.getFilter(AGED).accept(p);
searchUsage.getFilter(AGED).accept(p1);
Person.printAgedPersons();
}
}
class Person{
private static List<Person> agedPersons = new ArrayList<>();
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(int age,String name){
this.age = age;
this.name = name;
}
public void filterAgedPerson(Person person){
if(person.getAge() > 58){
agedPersons.add(person);
}
}
public static void printAgedPersons(){
for(Person person : agedPersons){
System.out.println(person.getName());
}
}
}
When I replace following Lambda expression
searchCritertiaHolder.put(AGED, (Person p)-> {p.filterAgedPerson(p);});
with
searchCritertiaHolder.put(AGED, Person::filterAgedPerson);
it gives me compilation error. I am using java 8 and and compiling through eclipse. Why is this so? Why cannot I assign method reference for instance method of any arbitrary object to consumer functional interface?
Your definition of filterAgedPerson takes a Person as an argument, even though it is not a static method. It doesn't need to, and it shouldn't if you want to use it as a Consumer<Person>. What you are ending up with is something compatible with BiConsumer<Person, Person>.
It might help to think of it this way: method references to non-static methods always take an "extra" argument which is used as this.
The easiest way for you to fix this with your current code structure is to modify the filterAgedPerson method to not take a Person as an argument
public void filterAgedPerson() {
if (this.getAge() > 58) {
agedPersons.add(person);
}
}
As an aside, you might want to also consider making your filters Predicate<Person> instead of Consumer<Person> and moving the results handling elsewhere. This will give you more flexibility as things get more complicated.

Categories