面试都会问的Android开发之设计模式,聊聊设计模式6大原则

18 篇文章 0 订阅
17 篇文章 0 订阅

单一职责

对于一个类来说,应该只有一个原因引起它的变化,也就是他所承担的职责应该单一化,不应该承担不同的责任。一个类承担的职责越多说明耦合性越高,越不容易被复用。比如我们常用的用户管理类,里面包含了登录,登出等行为。而在登录登出行为中,一个要将用户信息写入到缓存,一个要从缓存中清楚用户信息。

那么根据单一职责,显然这里写入以及读取缓存具体的方法实现是不该属于此类的,UserManager类只关心登录登出即可,缓存要交给另外的类实现。代码类似如下:

public class UserManager {
    /**
     * 登录
     */
    void login(){
        HttpUtil.login(new Callback(){
            @Override
            void onSuccess(User user){
                //登录完成将user写入缓存
                UserCache.saveUser(user);
            }
        });
    }
    /**
     * 登出
     */
    void logout(){
        HttpUtil.logout(new Callback(){
            @Override
            void onSuccess(){
                //登出完成将user从缓存清除
                UserCache.clearUser();
            }
        });
    }
}

public class UserCache {
    static void saveUser(User user){
        Cache.getInstance().saveUser(user);
    }
    static void clearUser(){
        Cache.getInstance().clearUser();
    }
}

其中saveUser和clearUser被拿到单独的缓存类实现,而不是直接实现在UserManager里,单一职责的目的就是使其减少耦合,更容易维护。

开闭原则

一个模块或类应该对拓展开放,对修改关闭。就是说不应该去改变一个现有的类,而可以去给这个类进行拓展增加功能。举个例子,一个手机生产的时候是要有手机屏幕的,如果你想要加个手机壳自己加就行了,但是不应该把我的屏幕给拆了,而在代码上就要用到继承或接口来实现。

里氏替换原则

凡是父类出现的地方,子类都应该能替换父类,而不会出现错误和异常,也就是保证子类的行为和属性要与父类一致,可以对父类进行拓展补充。听上去其实也是对开闭原则的延伸。假设在用户缓存中,现有的UserCache是将用户信息缓存到SD卡,那么现在如果需求变更为除了缓存到SD卡外还要缓存到sp中一份。那么这个时候只要集成UserCache重写相关方法即可,而不是直接去修改UserCache,而在调用端直接替换UserCahe的初始化(其实应该将缓存抽象成接口,这个后面会说到)。

// 调用端
UserCache userCache = new UserCache();

public class UserCache {
    void saveUser(User user){
        Cache.getInstance().saveUser(user);
    }
    void clearUser(){
        Cache.getInstance().clearUser();
    }
}

修改为:

// 调用端
SpAndSdCache userCache = new SpAndSdCache();

public class SpAndSdCache extends UserCache{
    @Override
    void saveUser(User user) {
        super.saveUser(user);
        // 加入sp缓存
    }
    @Override
    void clearUser() {
        super.clearUser();
        // 清除缓存
    }
}

依赖倒置原则

高层模块不应该依赖于底层模块,而都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。所谓的“要面向接口编程,不要面向实现编程”。

依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。

比如上面的UserManager用户管理类中,直接获取UserManager实例调用login和logout方法,这⾥我们的⾼层模块,即登录界⾯也是⼀个细节实现类,该登录功能依赖的是UserManager这个实体类,即依赖了细节没有依赖抽象。⼀旦UserManager更改,或者我们实⽤其他⽤户管理类,那么这⾥登录⽅法都要全部进⾏改动。对此,我们可以将对UserManager 的依赖改为依赖抽象:

public class UserManager implements IUserManager{
    /**
     * 登录
     */
    @Override
    public void login(){
        HttpUtil.login();
    }
    /**
     * 登出
     */
    @Override
    public void logout(){
        HttpUtil.logout();
    }
}

调用方:
IUserManager userManager = UserManager.getInstance();
userManager.login();

依赖倒置原则的实现方法:

  • 每个类尽量提供接口或抽象类,或者两者都具备。
  • 变量的声明类型尽量是接口或者是抽象类。
  • 任何类都不应该从具体类派生。
  • 使用继承时尽量遵循里氏替换原则。

接口隔离原则

一个模块对另一个模块的依赖应该建立在最小的接口上,它不应该依赖不需要的接口,不同的功能要抽象成不同的接口。当一个接口过于庞大时就要考虑是否要拆分成不同模块的接口,其实这也是单一职责的补充。比如客户端可以使用sp键值对缓存和SD卡缓存,可能会这样设计接口:

public interface ICacheManager {
    // SD卡缓存
    void sdCache();
    // sp缓存
    void spCache();
}

//调用方
public class UserManager implements ICacheManager{
    @Override
    public void sdCache() {
    }
    @Override
    public void spCache() {
    }
}

这里就存在缺陷,如果一个调用方是需要sp缓存或者SD卡缓存的话是不需要去实现另一个接口的。为了符合接隔离原则可以这样拆分为两个接口,调用方需要哪个方法实现对应接口即可:

// SD卡缓存
public interface ISdCacheManager {
    void sdCache();
}
// sp缓存
public interface ISpCacheManager {
    void spCache();
}

// 调用方
public class UserManager implements ISdCacheManager,ISpCacheManager{
    @Override
    public void sdCache() {

    }
    @Override
    public void spCache() {

    }

接口隔离原则的实现方法

  • 接口尽量小,但是要有限度。一个接口只服务于一个子模块或业务逻辑。
  • 为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。
  • 了解环境,拒绝盲从。每个项目或产品都有选定的环境因素,环境不同,接口拆分的标准就不同深入了解业务逻辑。
  • 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。

迪米特法则

也称最小知法则,一个模块应该减少对其他模块的依赖,减少耦合。比如我们设计了用户管理类UserManager用来管理登录,登出等操作拱调用端调用,但是具体的登录登出中的写入,清空用户缓存功能调用端是不了解的。

总结

其实所有的设计原则及设计模式都是为了使系统能够更加易于维护,拓展。减少耦合,提高开发效率,使代码易读性更高。我们在编程时,要时刻以这些原则约束自己,养成良好的编码习惯。

关于设计模式的相关视频讲解可移步https://www.bilibili.com/video/BV1WL411s7zj/

作者:单总不会亏待你
链接:https://juejin.cn/post/7013357097635020808

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值