Durante a concepção de um modelo de carro, testes precisam ser realizados em protótipos para garantir a qualidade, a segurança e o desempenho do veículo. Parâmetros de dimensão como largura, altura, volume do porta-malas e distância entre eixos podem ser ajustados em cada teste na expectativa de melhorar o produto final. No entanto, tais ajustes podem também piorar o modelo não só na eficiência como na estética, um parâmetro relevante para o consumidor. Nesse caso, o modelo de carro deve ser revertido para o estado anterior ao teste. Uma classe CarModelSnapshot é responsável por armazenar em seus atributos as propriedades de um CarModel, recebidas através do construtor e recuperáveis através de operações getters. CarModel representa um modelo de carro e possui uma operação que cria um novo CarModelSnapshot e outra que recupera o estado de um snapshot existente. É responsabilidade de CarModelChecker armazenar uma instância de CarModelSnapshot sem conhecer seu estado interno e, quando é necessário retornar CarModel ao estado de algum CarModelSnapshot, recuperar esse estado e passá-lo a CarModel através da operação restoreCarSnapshot.
package memento;
public class Client {
public static void main(String[] args) {
CarModel carModel = new CarModel();
//Um modelo de carro é criado e seus atributos são definidos
carModel.setHeight(1.4f);
carModel.setWidth(1.8f);
carModel.setCargoVolume(1.3f);
carModel.setWheelbase(3.9f);
//Uma instância de CarModelChecker armazena o CarModel criado
CarModelChecker modelChecker = new CarModelChecker(carModel);
System.out.println("Model before adjustments: \n" + modelChecker.getCarModel().getCarInfo() + "\n\n");
//O método doAdjustments é chamado para alterar os valores do carro dentro de CarModelChecker.
modelChecker.doAdjustments(0.4f, -0.6f, 1, -1.8f);
System.out.println("Car after adjustments: \n" + modelChecker.getCarModel().getCarInfo() + "\n\n");
//Um teste é realizado e se o mesmo falhar, significa que o modelo deve retornar ao
//seu estado anterior, salvo em CarModelChecker
if(!testModel(modelChecker.getCarModel())){
modelChecker.undoAdjustments(); //método que retorna carModel ao estado salvo em CarModelSnapshot
System.out.println("Car after test failure: \n" + modelChecker.getCarModel().getCarInfo() + "\n\n");
}
}
//método que realiza um teste em CarModel para validar seus atributos.
public static boolean testModel(CarModel carModel){
float value = (carModel.getWheelbase()/carModel.getHeight())
* carModel.getWidth();
return value < 2*carModel.getWheelbase()
&& value > 2.5*carModel.getCargoVolume();
}
}
package memento;
public class CarModel {
private float height;
private float width;
private float cargoVolume;
private float wheelbase;
//método que restaura o estado de CarModel a partir de um Snapshot
public void restoreCarModel(CarModelSnapshot cp){
this.height = cp.getHeight();
this.width = cp.getWidth();
this.cargoVolume = cp.getCargoVolume();
this.wheelbase = cp.getWheelbase();
}
//Armazena os atributos atuais de CarModel em uma classe CarModelSnapshot,
//armazenando seu estado.
public CarModelSnapshot createSnapshot(){
return new CarModelSnapshot(
this.height,
this.width,
this.cargoVolume,
this.wheelbase
);
}
public String getCarInfo(){
return "Height: " + this.height +
"\nWidth: " + this.width +
"\nCargo volume: " + this.cargoVolume +
"\nWheelbase: " + this.wheelbase;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public float getWidth() {
return width;
}
public void setWidth(float width) {
this.width = width;
}
public float getCargoVolume() {
return cargoVolume;
}
public void setCargoVolume(float cargoVolume) {
this.cargoVolume = cargoVolume;
}
public float getWheelbase() {
return wheelbase;
}
public void setWheelbase(float wheelbase) {
this.wheelbase = wheelbase;
}
}
package memento;
public class CarModelSnapshot {
private final float height;
private final float width;
private final float cargoVolume;
private final float wheelbase;
//Ao instanciar o Snapshot, este recebe os atributos da classe CarModel
//que o criou
CarModelSnapshot(float height, float width, float cargoVolume, float wheelbase){
this.height = height;
this.width = width;
this.cargoVolume = cargoVolume;
this.wheelbase = wheelbase;
}
float getHeight() {
return height;
}
float getWidth() {
return width;
}
float getCargoVolume() {
return cargoVolume;
}
float getWheelbase() {
return wheelbase;
}
}
package memento;
public class CarModelChecker {
private CarModel carModel;
private CarModelSnapshot carModelSnapshot;
public CarModelChecker(CarModel carModel){
this.carModel = carModel;
}
public CarModelSnapshot getCarModelSnapshot() {
return carModelSnapshot;
}
public void setCarModelSnapshot(CarModelSnapshot carModelSnapshot) {
this.carModelSnapshot = carModelSnapshot;
}
public CarModel getCarModel() {
return carModel;
}
//método chamado quando os atributos de CarModel precisam ser modificados.
public void doAdjustments(float heightAdd, float widthAdd,
float cargoVolumeAdd, float wheelbaseAdd){
//A partir de CarModel, um snapshot com seu estado é criado
//e armazenado em CarModelChecker.
this.carModelSnapshot = carModel.createSnapshot();
carModel.setHeight(carModel.getHeight() + heightAdd);
carModel.setWidth(carModel.getWidth() + widthAdd);
carModel.setCargoVolume(carModel.getCargoVolume() + cargoVolumeAdd);
carModel.setWheelbase(carModel.getWheelbase() + wheelbaseAdd);
}
//Restaura o estado de CarModel para o do snapshot salvo
public void undoAdjustments(){
this.carModel.restoreCarModel(this.carModelSnapshot);
}
}