闲谈设计模式之里氏替换原则

闲谈设计模式之里氏替换原则

  • 里氏替换原则(Liskov Substitution Principle)
    • 代码示例分析
      • 书籍例子
      • Android设计模式代码示例
    • 总结

里氏替换原则(Liskov Substitution Principle)

里氏替换原则:里氏替换原则俗称LSP,其含义每一个类型S的对象假设为O1,都有一个T类型的对象为O2,当业务场景需要的是O1被当作O2使用,但不会导致程序出现问题,换言之就是基类使用定义的问题。通过对父类的使用或者引用,子类型被当作父类使用,但是其具体的内部细节不会发生变化影响真正的运行结果。

代码示例分析

书籍例子

还记得上一文我实现的书籍案例吗,现在就基于书籍案例写一个书籍购物车,代码如下:

public class BookShoppingCart {

    public void buy() {
        if (bookeSizeHashMap.isEmpty()){
            System.out.println("请确认你需要购买的商品购物车为空");
        }else {
            float price = 0;
            for (Map.Entry<String,BookeSize> entry:bookeSizeHashMap.entrySet()) {
                price+=entry.getValue().size*entry.getValue().baseBook.getBookPrice();
            }
            System.out.printf("您需要付款%f元",price);
        }
    }

    private HashMap<String,BookeSize> bookeSizeHashMap = new HashMap<>();

    public void add(BaseBook book){
        String key = book.getBookAuthor()+book.getBookName();
        if (bookeSizeHashMap.containsKey(key)){
            bookeSizeHashMap.get(key).add();
        }else {
            bookeSizeHashMap.put(key,new BookeSize(book));
        }
    }

    public void removeOneBook(BaseBook book){
        String key = book.getBookAuthor()+book.getBookName();
        if (bookeSizeHashMap.containsKey(key)){
            BookeSize bookeSize = bookeSizeHashMap.get(key);
            bookeSize.sub();
            if (bookeSize.getSize()<=0)
                bookeSizeHashMap.remove(key);
        }
    }

    private class BookeSize {
        private BaseBook baseBook;
        private int size = 1;

        public BookeSize(BaseBook baseBook) {
            this.baseBook = baseBook;
        }

        public void add() {
            size += 1;
        }

        private void sub() {
            if (size == 0) return;
            size -= 1;
        }

        public int getSize() {
            return size;
        }
    }
}

public class LSPDemo {

    public LSPDemo() {
        DiscountBook javaPrincipe = new DiscountBook(
                "javaPrincipe", 85.0F, "kille", price -> price*0.8F);

        BaseBook cPBook = new BaseBook("C语言设计",50.0F,"Tom");
        BaseBook baseBook = new BaseBook("Python语言设计",50.0F,"Tom");
        BookShoppingCart shoppingCart = new BookShoppingCart();
        shoppingCart.add(cPBook);
        shoppingCart.add(cPBook);
        shoppingCart.add(javaPrincipe);
        shoppingCart.add(baseBook);
        shoppingCart.removeOneBook(cPBook);
        shoppingCart.buy();
    }
}

结合BookShoppingCart 这个类中有两个方法一个是removeOneBook和一个add方法,通过对BaseBook的使用不管是打折的或者是不打折的书籍都能对HashMap进行添加或者移除,从而避免程序程序编译时运行时就会产生奔溃,并且在通过buy的方法能够准确的计算出价格,里氏替换原则实现的了java中的替换以及多态。为什么多态也能体现呢请看下文,

Android设计模式代码示例

还记得开闭原则的示例的代码吗?没错就是它,它不止是体现了开闭原则也体现了里氏替换原则更体现了java的多态
为什么这样说呢?因为ImageCache,代码接招

public interface ImageCache {
    void put(String url, Bitmap bitmap);

    Bitmap get(String url);
}
public class ImageLoader {
    //获取图片缓存
    ImageCache imageCache = null;
    public void setImageCache(ImageCache imageCache) {
        this.imageCache = imageCache;
  
 }
}

众所周知多态是由接口实现这一思维去实现,而通过对接口这一类型的作为一个基类的声明以及使用,实现它的子类也就是进行调用转换的时候是不会影响其子类的行为,所以在lmageloader这个示例代码可以通过使用,不同的图片缓存声明并实现,然后调用并不影响其实际实例对象起行为,所以说上文开闭原则中这个例子技能体现开闭原则也能体现里氏替换原则。

总结

六大原则并不是冲突的,往往一个好的程序亦或是一段的好的代码都能体现出其设计模式以及其原则的糅合。
里氏替换原则保证了程序子类作为父类使用的优点,但是父类转子类往往容易出现问题,其核心基点就是抽象。
这不难体现与细节依赖于抽象,而抽象不依赖于细节。

你可能感兴趣的:(java设计模式,kotlin设计模式,Android进阶,设计模式)