My main questions: FileWithSave handles its saving itself, but delegates it to a repository object. This allows implementation details to be available without being present in the API when saving (transpose this to a Mail sending API as well, available for send but not public). Is this OK in terms of OOP practices? Are there any maintainence gotchas I'm missing? Does it need reorganization?
Without save:
package com.example.external;
public interface File {
/**
* Get the unique identifier.
*
* @return unique identifier.
*/
String getId();
/**
* Get the file name.
*
* @return file name.
*/
String getName();
/**
* Sets name for the file.
*
* @param name file name.
*/
void setName(String name);
/**
* Get the file size.
*
* @return file size.
*/
Long getSize();
}
Without save implementation:
package com.example.internal;
public class FileImpl implements File {
// I don't want it in my public signature but I want it when I'm saving for some reason :(
private Something somethingPrivate;
private final String id;
private final String name;
private final Long size;
public FileImpl(String id, Long size) {
this.id = id;
this.size = size;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getSize() {
return size;
}
}
Repository for File:
package com.example.external;
public interface FilingCabinet {
/**
* Get a file from the cabinet.
*
* @param id unique identifier.
* @return file.
*/
File get(String id);
/**
* Store a file in the cabinet.
*
* @param file.
*/
void store(File file);
}
Without save client sample code:
FilingCabinet cabinet = room.getFilingCabinet();
File file = cabinet.get("my-unique-id");
file.setName("my-new-name");
cabinet.store(file);
With save:
package com.example.external;
public interface FileWithSave extends File {
/**
* Save the changes.
*/
File store();
}
With save implementation:
package com.example.internal;
public class FileWithSaveImpl implements FileWithSave {
private Something somethingPrivate;
private final String id;
private final String name;
private final Long size;
private final PrivateFilingCabinet repo;
public FileWithSaveImpl(String id, Long size, PrivateFilingCabinet repo) {
this.id = id;
this.size = size;
this.repo = repo;
}
@Override
public String getId() {
return id;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public Long getSize() {
return size;
}
@Override
public void store() {
repo.save(this);
}
}
Wrapper class:
package com.example.external;
/**
* Wraps PrivateFilingCabinet and injects PrivateFilingCabinet in FileWithSave object.
*/
public interface Secretary {
/**
* Get the file for someone.
*
* @param unique identifier.
* @return file.
*/
FileWithSave getFile(String id);
}
Repository injected in to FileWithSave and not part of the public API package:
package com.example.internal;
public interface PrivateFilingCabinet {
/**
* Get a file from the cabinet.
*
* @param id unique identifier.
* @return file.
*/
FileWithSaveImpl get(String id);
/**
* Store a file in the cabinet.
*
* @param file.
*/
void store(FileWithSaveImpl file);
}
With save client sample code:
FileWithSave file = company.getSecretary().getFile("my-unique-id");
file.setName("my-new-name");
file.store();