ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

夯实设计原则之里氏替换原则

2021-05-14 18:01:37  阅读:142  来源: 互联网

标签:name 原则 里氏 void mobileNo 用户 夯实 public String


All Rights Reserved © jackiegu.cn

理念:

所有引用基类(父类)的地方必须能透明的使用其子类的对象;

在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象;如:小明喜欢动物,那么他一定喜欢猫,因为猫是动物的子类;反过来,小明喜欢猫,不能据此断定出他喜欢动物,可能他并不喜欢狗,虽然狗也是动物;

里氏替换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,再在运行时确定其子类类型,用子类对象来替换父类对象;

案例:

小明在工作中接到一个需求,需要为项目中的普通用户和VIP用户发送短信;于是他先定义了两个用户类:NormalUser普通用户、VipUserVIP用户,如下:

/**
 * 普通用户
 */
public class NormalUser {

    private String name;

    private String mobileNo;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMobileNo() {
        return mobileNo;
    }

    public void setMobileNo(String mobileNo) {
        this.mobileNo = mobileNo;
    }
}
/**
 * VIP用户
 */
public class VipUser {

    private String name;

    private String mobileNo;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMobileNo() {
        return mobileNo;
    }

    public void setMobileNo(String mobileNo) {
        this.mobileNo = mobileNo;
    }
}

然后他再定义了一个短信发送器类SmsSender,里面分别实现了对普通用户和VIP用户的短信发送功能,如下:

/**
 * 短信发送器
 */
public class SmsSender {

    /**
     * 给普通用户发送短信
     *
     * @param normalUser 普通用户
     */
    public void send(NormalUser normalUser) {
        System.out.println("发送短信给用户: " + normalUser.getMobileNo());
    }

    /**
     * 给VIP用户发送短信
     *
     * @param vipUser VIP用户
     */
    public void send(VipUser vipUser) {
        System.out.println("发送短信给用户: " + vipUser.getMobileNo());
    }
}

从上面的案例来看, SmsSender类中给普通用户和VIP用户发送短信的逻辑是一样的,很明显的有代码重复;而且在项目中如果新增了一种超级用户的用户类型,也需要发送短信时,那就不得不修改SmsSender类的代码,也就违背了开闭原则;

同样是上面的案例,当懂得里氏替换原则的小红遇到时,会怎样来设计呢?接下来请看:

首先定义一个用户行为接口类IUser,如下:

/**
 * 用户行为接口
 */
public interface IUser {

    String getName();

    void setName(String name);

    String getMobileNo();

    void setMobileNo(String mobileNo);
}

然后再重新定义普通用户NormalUser和VIP用户VipUser类,让这两个用户类都实现IUser接口,如下:

/**
 * 普通用户
 */
public class NormalUser implements IUser {

    private String name;

    private String mobileNo;

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String getMobileNo() {
        return mobileNo;
    }

    @Override
    public void setMobileNo(String mobileNo) {
        this.mobileNo = mobileNo;
    }
}
/**
 * VIP用户
 */
public class VipUser implements IUser {

    private String name;

    private String mobileNo;

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String getMobileNo() {
        return mobileNo;
    }

    @Override
    public void setMobileNo(String mobileNo) {
        this.mobileNo = mobileNo;
    }
}

最后重新定义短信发送器类SmsSender,如下:

/**
 * 短信发送器
 */
public class SmsSender {

    /**
     * 给用户发送短信
     *
     * @param user 用户
     */
    public void send(IUser user) {
        System.out.println("发送短信给用户: " + user.getMobileNo());
    }
}

从上面小红的代码来看, SmsSender类中给不同用户发送短信的重载方法已不存在,同时新增了一个以IUser为参数的发送短信的方法,以后不管为什么类型的用户类型发送短信,都可以采用这个方法;解决了小明版本的代码重复问题,同时在新增用户类型发送短信时也不用去修改SmsSender类的代码,遵循了开闭原则,SmsSender类的send方法的IUser参数也遵循了里氏替换原则;

标签:name,原则,里氏,void,mobileNo,用户,夯实,public,String
来源: https://blog.csdn.net/gu19930914/article/details/116799125

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有