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.