Fernando y Jorge, contribuidores de esta página, dieron este webinar en Software Gurú Campus.
Las diapositivas en Slide Share
public static void main(String[] args) {
double notANumber = Double.NaN;
System.out.println(notANumber == Double.NaN);
}
Si tenemos una objeto o1 de la clase A y un objeto o2 de la clase B entonces en un programa escrito en función de B podemos sustituir el objeto o1 por o2 si alterar la funcionalidad del sistema si A es un subtipo de B.
public class LiskovSustitution {
public static void main(String[] args) {
OtroItem o1 = new OtroItem();
Item o2 = new Item();
hacerAlgo(o1); Aquí podemos reemplazar o1 por o2 sin afectar la funcionalidad.
}
static void hacerAlgo(Item b){
b.update();
}
}
class OtroItem extends Item{
public void hacerOtraCosa(){
System.out.println("Hacer otra cosa");
}
}
class Item{
public void update(){
System.out.println("Item updated");
}
}
public class LiskovSustitution {
public static void main(String[] args) {
OtroItem o1 = new OtroItem();
Item o2 = new Item();
hacerAlgo(o1); Aquí podemos reemplazar o1 por o2.
}
static void hacerAlgo(Item b){
b.update();
}
}
class NoUpdatableItem extends Item{
public void update (){
throw UnsoportedOperation();
}
}
class Item{
public void update(){
System.out.println("Item updated");
}
}
public class LiskovSustitution {
public static void main(String[] args) {
OtroItem o1 = new OtroItem();
Item o2 = new Item();
hacerAlgo(o1); Aquí podemos reemplazar o1 por o2.
}
static void hacerAlgo(Item b){
if( ! b instanceof NoUpdatableItem)
b.update();
}
}
class NoUpdatableItem extends Item{
public void update (){
throw UnsoportedOperation();
}
}
class Item{
public void update(){
System.out.println("Item updated");
}
}
class Item{
String nombre;
public Item(final String nombre){
this.nombre=nombre;
}
}
class UpdatableItem extends Item{
public UpdatableItem(String nombre) {
super(nombre);
}
public void update(){
System.out.println("Update item");
}
}
class NoUpdatableItem extends Item{
public NoUpdatableItem(String nombre) {
super(nombre);
}
}
package gildedrose;
class GildedRose {
Item[] items;
public GildedRose(final Item[] items) {
this.items = items;
}
public void updateQuality() {
for (int i = 0; i < items.length; i++) {
if (!items[i].name.equals("Aged Brie")
&& !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) {
if (items[i].quality > 0) {
if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
items[i].quality = items[i].quality - 1;
}
}
} else {
if (items[i].quality < 50) {
items[i].quality = items[i].quality + 1;
if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) {
if (items[i].sellIn < 11) {
if (items[i].quality < 50) {
items[i].quality = items[i].quality + 1;
}
}
if (items[i].sellIn < 6) {
if (items[i].quality < 50) {
items[i].quality = items[i].quality + 1;
}
}
}
}
}
if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
items[i].sellIn = items[i].sellIn - 1;
}
if (items[i].sellIn < 0) {
if (!items[i].name.equals("Aged Brie")) {
if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) {
if (items[i].quality > 0) {
if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
items[i].quality = items[i].quality - 1;
}
}
} else {
items[i].quality = items[i].quality - items[i].quality;
}
} else {
if (items[i].quality < 50) {
items[i].quality = items[i].quality + 1;
}
}
}
}
}
}
Veamos el Sistema ya con los cambios: package gildedrose;
public class GildedRoseSystem {
private ItemUpgradeInstanceable factory;
public GildedRoseSystem() {
this(GildedRoseMainFactory.getItemUpgradableFactory());
}
public GildedRoseSystem(final ItemUpgradeInstanceable factory) {
this.factory = factory;
}
public void updateItem(final Item item) {
ItemUpgradeable upgratable = this.factory.getInstance(item);
upgratable.updateQuality(item);
upgratable.updateSellIn(item);
}
}
El sistema tiene como responsabilidad es actualizar de cada tipo de queso(item) su calidad y su fecha limite de venta, sin siquiera saber el detalle de como se actualiza cada propiedad de los tipos de quesos, ni que reglas de negocio aplican para cada propiedad y tipo de queso, su responsabilidad es clara, modular y encapsulada.package gildedrose;
public class NormalItemUpgradeable implements ItemUpgradeable {
private GildedRoseBusiness business;
public NormalItemUpgradeable() {
business = new GildedRoseBusiness();
}
@Override
public void updateQuality(final Item item) {
this.business.degreteQualityInOne(item);
if (item.sellIn <= 0) {
business.degreteQualityInOne(item);
}
}
@Override
public void updateSellIn(final Item item) {
this.business.degreteSellIn(item);
}
}
Los quesos normales saben que su calidad se degrada en uno y que si su fecha de venta limite ya paso se degrada al doble, ha reglas de negocio que se aplican a dicho degradado pero es una responsabilidad que no es propia del tipo de queso. Veamos otro tipo de queso:package gildedrose;
public class BackstageSpecialItemUpgradeable implements ItemUpgradeable {
private GildedRoseBusiness business;
public BackstageSpecialItemUpgradeable() {
business = new GildedRoseBusiness();
}
@Override
public void updateQuality(final Item item) {
business.incrementQualityInOne(item);
updateQualityInSpecialSellinTime(item);
}
@Override
public void updateSellIn(final Item item) {
business.degreteSellIn(item);
}
private void updateQualityInSpecialSellinTime(final Item item) {
if (item.sellIn < 11)
business.incrementQualityInOne(item);
if (item.sellIn < 6)
business.incrementQualityInOne(item);
if (item.sellIn <= 0)
item.quality = item.quality - item.quality;
}
}
Este queso a diferencia del normal aumenta su calidad con forme se acerca a su fecha limite de venta en uno, dos o tres dependiendo el rango de proximidad a dicha fecha y una ves que llega a la fecha la calidad es cero, a cada incremento se le aplica una regla de negocio que no es responsabilidad como tal de el queso.package gildedrose;
public class GildedRoseBusiness {
public void degreteSellIn(Item item) {
if (!item.name.equals("Sulfuras, Hand of Ragnaros")) {
item.sellIn = item.sellIn - 1;
}
}
public void incrementQualityInOne(Item item) {
if (item.quality < 50) {
item.quality = item.quality + 1;
}
}
public void degreteQualityInOne(Item item) {
if (item.quality > 0) {
item.quality = item.quality - 1;
}
}
}
Ven esta clase se encuentran todas las definiciones del negocio en cuanto al decremento e incremento de la calidad sin importar como las aplique cada item y al decremento de la fecha limite.