Safe alternative to calling of abstract method from constructor - java

I know it's a bad idea, and it causes bugs. The problem is, I need the "intended" behavior.
"Low":
// simplified example
abstract class Low {
String name;
public Low(String name) {
this.name = name;
}
public Low(int id) {
this.name = getNameForId(id);
}
public Low() {} // will be loaded later
#Override
public String toString()
{
return name;
}
public void load(InputStream in) {
// --- grab ID from stream ---
this.name = getNameForId(id);
}
protected abstract String getNameForId(int id);
}
And "High":
class High extends Low {
public High(int id) { super(id); }
public High(String name) { super(name); }
public High() {} // will be loaded later
#Override
protected String getNameForId(int id)
{
return Registry.getName(id);
}
}
Note that in this particular case, it will work just fine. But it will fall apart once the overriding method needs to use some field.
How to do this better?

You want to separate out loading a name for an ID from your Low and High objects. Introduce an interface for loading names given an ID.
public interface NameProvider
{
String getNameForId(String id);
}
Add specific implementations for each source of names.
public class InputStreamNameProvider implements NameProvider
{
private InputStream inputStream;
// Constructor
public String getNameForId(String id)
{
// return name loaded via inputStream
}
}
public class RegistryNameProvider implements NameProvider
{
public String getNameForId(String id)
{
return Registry.getName(id);
}
}
You could then add a new constructor to Low that takes the NameProvider and String id as arguments
public Low(NameProvider provider, String id)
{
this(provider.getNameForId(id));
}
or even use the name provider before constructing the instance of Low or High. The main idea is the separation of loading the name for an ID from the Low and High objects.

You can avoid calling the abstract method by adding a public void load(int id) method (like you do for InputStream) and removing the Constructor(int id).
You might want to add some Factory functionality to ensure your constructed instance is can never be accessed without having a proper name value.

Related

downcast to subclass and get subclass only fields

I have classes similar to DataRequest & DataWithIdRequest. DataWithIdRequest gets passed into my controller method. I want to pass the subclass object ONLY to another class for processing. However, when I try to downcast to DataRequest the extra field is still showing. How can I accomplish this?
public class DataRequest {
private String name;
public String getName() {
return name;
}
public void setFirstName(String name) {
this.name = name;
}
}
public class DataWithIdRequest extends DataRequest {
private Integer id;
public Integer getId() {
return contractKey;
}
public void setContractKey(Integer id) {
this.id = id;
}
}
//controller
processData(request);
}
//domain class
public Boolean processData(DataRequest request) {
//request here has DataWithIdRequest field
//but I only want the subclass
}
public Boolean processData(DataRequest request) { }
Because in your method processData, request's type is DataRequest. You want it to be DataWithIdRequest.
public Boolean processData(DataWithIdRequestrequest request) { }
You can only offer a part of an API (application programmer's interface), by separating the code in an interface.
public interface Identified {
Integer getId();
public void setContractKey(Integer id);
}
public class DataWithIdRequest extends DataRequest implements Identified {
private Integer id;
#Override
public Integer getId() {
return contractKey;
}
#Override
public void setContractKey(Integer id) {
this.id = id;
}
}
public Boolean processData(DataRequest request) {
if (request instanceOf Identified identified) {
identified.setContractKey(13);
}
}
Or move the problem to the caller:
public Boolean processData(Identified request) {
request.setContractKey(13);
}
By the way it more usual to use int, boolean, the primitive types.
To hide the information completely, you need to create a new instance of DataRequest by DataWithIdRequest (that's why mapping library like mapstruct is useful), but not directly passing it.
Explanation:
This is how inheritance works, imagine a method takes a parameter of an interface or abstract class, by using instanceof inside the method we can check the object actual type and do something specific. e.g.
public void drawShape(Shape shape) {
if (shape instanceof Circle) {
Circle circle = (Circle) shape;
// do sth
} else if (shape instanceof Square) {
// do sth else
}
}
The above example is completely valid (although not a good programming style, that's another story).
The object inside the memory holds all the actual class details, passing it to a method doesn't change anything to the memory. The parameter (e.g. shape) is only another reference to the same memory location.
Maybe I don't understand the question fully but: as you want I it's not possible since:
public class DataWithIdRequest extends DataRequest
means DataRequest is a subset of DataWithIdRequest, it's an intersection.
You unfortunately need to find an other way

Builder pattern vs encapsulation of a data

How should I retain Encapsulation Principle of OOP, when using builder pattern? I mean fact that builder should provide abstraction layer between object and the code that uses it, so that it can be constructed part-by-part, requires either making setter for every parameter of an object that we would normally pass in the constructor. That again may be undesirable in some cases, as I don't want client to be able to modify value that I have to via builder. Example to picture what I mean is below:
public class Cat
{
private string _race;
private string _name;
public Cat()
{
_race = "common";
_name = string.Empty;
}
public void setRace(string race) { _race = race; }
public void setName(string name) { _name = name; }
}
public class CatBuilder
{
private Cat _objectUnderConstruction;
public CatBuilder() { _objectUnderConstruction = new Cat(); }
public CatBuilder WithName(string name)
{
_objectUnderConstruction.setName(name);
return this;
}
public CatBuilder OfRace(string race)
{
_objectUnderConstruction.setRace(race);
return this;
}
}
This is not production code, I wrote it now with presentation in mind, so do not get mad on how it is constructed.
In the example above there is need to set cat's race, as we need that information for the purpose of object filling, so we need to pass info into it. At the same time I don't want anyone to ever change race of my cat during its lifetime (e.g. it would change from egyptian to british in the middle of processing) Normally I would get rid of accessor method, but I need for the builder. This way, encapsulation of data is hurt (because straight get and set aren't encapsulating anything), and I want to avoid it.
This example is simple and I could pass parameter in constructor, but imagine bigger class, where there is a lot of such fields, what in this case? Should I pass some configuration object inside (which is almost like builder, but simpler, hence builder is pointless) or pass the builder itself to the constructor (which is weird, but what do I know)?
How I should do that?
If your builder is tightly-coupled with your class you can make Builder subclass of the object being constructed:
public class Cat
{
private string _race;
private string _name;
public Cat()
{
_race = "common";
_name = string.Empty;
}
private void setRace(string race) { _race = race; }
private void setName(string name) { _name = name; }
public class Builder
{
private Cat _objectUnderConstruction;
public CatBuilder() { _objectUnderConstruction = new Cat(); }
public CatBuilder WithName(string name)
{
_objectUnderConstruction.setName(name);
return this;
}
public CatBuilder OfRace(string race)
{
_objectUnderConstruction.setRace(race);
return this;
}
}
}
This way, you'll be able in Builder to access private fields and methods of Cat and use it like new Cat.Builder().OfRace("").OfName("").Build().

Memento pattern drawbacks

So, here is an typical implementation of Memento pattern (skipped getters and setters).
public class Employee {
private String name;
private String phone;
public EmployeeMemento save() {
return new EmployeeMemento(name, phone);
}
public void revert(EmployeeMemento memento) {
this.name = memento.getName();
this.phone = memento.getPhone();
}
}
public class EmployeeMemento {
private final String name;
private final String phone;
public EmployeeMemento(String name, String phone) {
this.name = name;
this.phone = phone;
}
}
public class Caretaker {
private Stack<EmployeeMemento> history;
public Caretaker() {
history = new Stack<>();
}
public void save(Employee employee) {
history.push(employee.save());
}
public void revert(Employee employee) {
employee.revert(history.pop());
}
}
All implementations of this pattern that I found are more or less equal to the one above. But there are some problems about this kind of implementation, that I don't like:
It's possible to triger both employee.revert() and caretaker.revert(employee). I would like to have only one access point.
If we want to change EmployeeMemento, we have to make changes in Employee class also (because of revert method).
Is there a way to overcome this?
Or maybe I pay too much attention, and this details are not so important?
1) Note that Caretaker is supposed to take care of holding Mementos, not necessarily take care of Undo/Redo. If you look at the various implementations on Internet (For example here), you'll see that Caretaker does not have revert() but usually something like getMemento(). So the class that takes care of Undoing, is someone else which calls getMemento() on Caretaker and then revert() on Subject.
Even if you want Caretaker to take care of Undoing, note that employee.revert() is a method that's solely created to be used by caretaker.revert(), because in this design, no one else has access to Mementos. You can reduce it's visibility to be visible by only Caretaker. (If this was C++, it would be easily done by use of friend, but in Java you have to be creative and use package visibility or some other way.)
2) In Memento pattern, a class and its Memento are tightly coupled. Actually it's only the class itself that has access to Memento's internals and no one else should see how Memento is composed. So it does not matter if a change to class, propagates to its Memento.
Then again If you want to isolate changes, you can be creative again. For example instead of duplicating name and phone in both Class and its Memento, you could extract another class which contains these fields (let's say by the name of State) and then use this State in both the original class and its Memento. This way, when you have changes to state of the class, you need only to modify State.
Side note: It's better to define Memento as a nested static class inside the Subject.
So my design, that addresses your issues, would be something like this:
public class Employee {
private State state;
public Memento save() {
return new Memento(state);
}
public void revert(Memento memento) {
this.state = memento.state;
}
public static class Memento {
private final State state;
public Memento(State state) {
this.state = state;
}
}
public static class State {
private String name;
private String phone;
}
}
public class Caretaker {
private Stack<Employee.Memento> history;
public Caretaker() {
history = new Stack<>();
}
public void addMemento(Employee.Memento memento) {
history.push(memento);
}
public Employee.Memento getMemento() {
return history.pop();
}
}
public class UndoHandler {
Employee employee;
Caretaker caretaker;
public void snapshot() {
caretaker.save(employee.save());
}
public void undo() {
employee.revert(caretaker.getMemento());
}
}

Suggestions on how to create a changewatcher on a SlingModel to enable persistence to the JCR

We are currently attempting to implement an extension to SlingModels, to allow a slingmodel to be persisted to the JCR directly.
Our strategy has 2 considered starting conditions:
1. A new object that is to be persisted
2. An object that has been retrieved from the JCR, altered, and is then to be persisted again
For situation 1, we are using reflection to examine the object, create a new node for the model, insert properties for any of the primitive variables found, and recursively use the same persistence approach for any complex model objects found as variables, and collections.
My question on best approach relates to situation 2. If we pull out an object from the repository, we cannot be guaranteed that the node will not be synchronously changed in the meantime. Thus, we would like to implement a change watcher on the SlingModel that keeps a transaction journal on any changes made. The transactions can then be used to set the relevant properties when persisting the object back to the JCR again.
I have considered using an observer pattern, but this would mean that we would need to implement a function within the setter on each SlingModel, which is not ideal at all, as it requires a developer to remember to add the code and do it correctly.
Ideally, I would like to implement something like an interceptor directly on the variable, or if not possible, on the setter itself, and mandate that each model would then need to use a getter/setter for each variable. We can configure code scanning tools to enforce developers to implement getter/setters.
What would the be the best way to approach the change watcher here?
import java.util.List;
public class Teacher {
private String userName;
private String cource;
private List<Student> students;
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getCource() {
return cource;
}
public void setCource(String cource) {
this.cource = cource;
}
}
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class ClassFacadeCglib implements MethodInterceptor{
private Object target;
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// callback method
enhancer.setCallback(this);
// create proxy object
return enhancer.create();
}
#Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
if(method.getName().startsWith("set")){
System.out.println(method.getName()+" start");
proxy.invokeSuper(obj, args);
System.out.println(method.getName()+" end..");
}
if(method.getName().startsWith("get")){
System.out.println(method.getName()+" start");
proxy.invokeSuper(obj, args);
System.out.println(method.getName()+" end");
}
return null;
}
}
public class Main {
public static void main(String[] args) {
ClassFacadeCglib cglib=new ClassFacadeCglib();
Teacher teacher=(Teacher)cglib.getInstance(new Teacher());
teacher.setCource("Math");
teacher.getUserName();
}
}
Note :
cglib-full-2.0.2.jar is required for running.
see https://repo1.maven.org/maven2/cglib/cglib-full/2.0.2/

Get Object from Field

CLARIFICATION:
I do not know the objects name. That is where the problem comes in. I am creating an object like such:
`new Object(String attributes);
I am trying to run code in another class such as:
***.getStuff();
the trick to it is, there is no name for the Object. but i do know what String attributes is
The question: Is there any way to accomplish this without using the dreaded for loop?
This question is a bit tricky to word, but I will try my best. What I want to is get an object that matches a particular field without making a messy for loop. Something along the lines of:
Object A has the field String name.
String nameObj = "Tickle";
Object A has the name "Tickle"
if(nameObj.equals(Object A)){
//bla bla
}
Very confusing wording, yes. Sorry about that. I want to use Object A in my code without having to figure out which object it is, assuming all I have is its name. I am looking for a shortcut around using a for loop, I suppose.
Feel free to ask questions about what I am looking for. Sorry about the terribly worded question.
Poor coding, but this is what I am looking for...
nameObj.getName().getObjectA();
If you have a bunch of objects with names, and you want to grab an object by its name, I suggest you look up the class HashMap. HashMap lets you put in objects under keys, and when you give the hash map a key it returns the object associated with that key. So in your example, the keys would be string names.
Take at this implementation, that demonstrates what #Patashu said, create a map to the objects, in this case I just add an abstract class at the top of all.
import java.util.HashMap;
public class FindMeBaby {
public static void main(String[] args) {
Factory.add(new NiceGuy("first one"));
Factory.add(new FirstChild("ok im late"));
System.out.println(Factory.get("first one")
.getVeryImportantInformationThatOnlyThisClassKnows());
}
}
abstract class ParentOfAll {
protected String id;
public ParentOfAll(String id) {
this.id = id;
}
public String getId(){
return id;
}
public abstract String getVeryImportantInformationThatOnlyThisClassKnows();
}
class FirstChild extends ParentOfAll {
public FirstChild(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "this is a secret";
}
}
class NiceGuy extends ParentOfAll {
public NiceGuy(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "to say the true, i'm not that nice :)";
}
}
class Factory {
private static HashMap allTheObjects = new HashMap();
public static Object add(ParentOfAll object) {
allTheObjects.put(object.getId(), object);
return object;
}
public static ParentOfAll get(String key) {
return (ParentOfAll) allTheObjects.get(key);
}
}
This is another version, of the same implementation with a more transparent aproach, without the Factory class, the Parent itself will keep track of the instances and save in a list.
import java.util.HashMap;
public class FindMeBaby {
public static void main(String[] args) {
NiceGuy foo = new NiceGuy("first one");
FirstChild bar = new FirstChild("ok im late");
System.out.println(ParentOfAll.get("first one")
.getVeryImportantInformationThatOnlyThisClassKnows());
}
}
abstract class ParentOfAll {
protected String id;
public ParentOfAll(String id) {
this.id = id;
add(this);
}
public String getId() {
return id;
}
public abstract String getVeryImportantInformationThatOnlyThisClassKnows();
private static HashMap allTheObjects = new HashMap();
private static Object add(ParentOfAll object) {
allTheObjects.put(object.getId(), object);
return object;
}
public static ParentOfAll get(String key) {
return (ParentOfAll) allTheObjects.get(key);
}
}
class FirstChild extends ParentOfAll {
public FirstChild(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "this is a secret";
}
}
class NiceGuy extends ParentOfAll {
public NiceGuy(String id) {
super(id);
}
public String getVeryImportantInformationThatOnlyThisClassKnows() {
return "to say the true, i'm not that nice :)";
}
}

Categories

Resources