接口隔离原则

个人博客原文:
接口隔离原则

设计模式六大原则之四:接口隔离原则。

简介

姓名 :接口隔离原则

英文名 :Interface Segregation Principle

价值观 :宁缺毋滥

个人介绍

  1. Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该依赖它不需要的接口。)
  2. The dependency of one class to another one should depend on the smallest possible interface.(类间的依赖关系应该建立在最小的接口上。)

也用一个故事来讲这 2 句干巴巴的定义。

一小伙子跑到大城市的工厂打工,工作了一年半载,越来越觉得没劲,每天干那么多活,又领那么一点工资,和他老爸抱怨这段时间的困扰,老爸想着,家里有个小作坊,自己也一年不如一年了,要不就让儿子回老家管理这小作坊。小伙子熬不过这个年,就跑回老家跟着老爸打理小作坊。

布娃娃

(来自Google Image)

小作坊主要是做布娃娃的,如上图,工作在于打扮包装布娃娃,工序有给布娃娃扎辫子、穿衣服、包装入箱、打标签。整个完整的流程都是一个人做的。有很多个工人每天都在做这个事情。

老爸向小伙子诉苦,感觉招工挺多人的,生产力还是提不上去。小伙子记着老爸的话,在工厂里面观察了几天,他发现每个工人都要做这 4 个打扮包装布娃娃的工序,有些工人扎辫子很快但穿衣服很慢,有些工人扎辫子很慢但穿衣服快,他用了笔记本记下来:李大姨扎辫子快,王大妈穿衣服快,就这样把每个人有效率的工作都记录下来。

一天晚上吃饭,小伙子跟老爸说了自己观察到的现象,也把本子拿给老爸看,跟老爸商量:可不可以做个尝试,不要每个人负责打扮包装布娃娃全步骤,而是按工序分开,每个人只负责一个工序,每个工人只干一件事,更容易熟能生巧。老爸听着觉得有道理。

第二天早上,就到小作坊里,召集了所有工人,按小伙子的笔记上面的名单分工,大家都做好各自负责的内容,像流水线一样,做好了就放到下个工序的地方,让下个工序的人去做。到了下班,小伙子清点了今天工作的成果,包装完成的娃娃比前一天多了 50% 。晚上小伙子跟老爸喝着百威吃起大肉庆祝一番。

这个故事你看了可能想骂爹骂娘,跟上面的定义有啥毛关系?故事只是把大家带入这个场景,我们在工作中,着手开发之前不都得先理清好需求背景,这就是要讲接口隔离原则的背景,通过代码来给大家讲解一下如何用好接口隔离原则。

父亲的运营模式

先看代码

interface Work {

    void hairBraiding();
    void getDressed();
    void packingIntoTheBox();
    void makeTag();

}

class WangMather implements Work{

    @Override
    public void hairBraiding() {
        System.out.println("王大妈给布娃娃扎辫子");
    }

    @Override
    public void getDressed() {
        System.out.println("王大妈给布娃娃穿衣服");
    }

    @Override
    public void packingIntoTheBox() {
        System.out.println("王大妈把布娃娃装入箱子");
    }

    @Override
    public void makeTag() {
        System.out.println("王大妈给箱子打标签");
    }
}

class LiAunt implements Work {

    @Override
    public void hairBraiding() {
        System.out.println("李大姨给布娃娃扎辫子");
    }

    @Override
    public void getDressed() {
        System.out.println("李大姨给布娃娃穿衣服");
    }

    @Override
    public void packingIntoTheBox() {
        System.out.println("李大姨把布娃娃装入箱子");
    }

    @Override
    public void makeTag() {
        System.out.println("李大姨给箱子打标签");
    }
}

// 测试代码
WangMather wangMather = new WangMather();
wangMather.hairBraiding();
wangMather.getDressed();
wangMather.packingIntoTheBox();
wangMather.makeTag();

LiAunt liAunt = new LiAunt();
liAunt.hairBraiding();
liAunt.getDressed();
liAunt.packingIntoTheBox();
liAunt.makeTag();

在父亲管理下的小作坊,是大家各自完成好一个布娃娃,工作互不交接,在这种运营模式下,我们把所有工作都合并在一个接口 Work 是没有问题的。有人可能要问,不是说接口隔离么?这里面 Work 接口的 4 个方法都可以分离开,它们都是各自的工作内容。稍等一下,我们现在是基于老父亲运营的模式下实现,如果小作坊一直都是这种模式运营,这段代码有问题么?其实没问题的,我们根据当时的业务考虑,在这种情况下,把 Work 抽成 4 个接口不是不可以,只是不现实,每个工人都去实现一模一样的 4 个接口在老父亲运营模式下是不切实际。

儿子的运营模式

接下来介绍儿子的运营模式。儿子提倡的是每个工人职责分明,只负责一个事情,在这种情况下,如果还是用老父亲的 Work 接口会有什么问题呢?上面我们说了,李大姨扎辫子快,王大妈穿衣服快,所以李大姨被分配去给布娃娃扎辫子,王大妈被分配去给布娃娃穿衣服。我们沿用老父亲的 Work 接口实现,代码如下

class WangMather2 implements Work{

    @Override
    public void hairBraiding() {
    }

    @Override
    public void getDressed() {
        System.out.println("王大妈给布娃娃穿衣服");
    }

    @Override
    public void packingIntoTheBox() {
    }

    @Override
    public void makeTag() {
    }
}

class LiAunt2 implements Work {

    @Override
    public void hairBraiding() {
        System.out.println("李大姨给布娃娃扎辫子");
    }

    @Override
    public void getDressed() {
    }

    @Override
    public void packingIntoTheBox() {
    }

    @Override
    public void makeTag() {
    }
}

看出问题来了么?李大姨仅仅参与扎辫子工作,王大妈参与了穿衣服工作,但是却都要依旧实现其他 3 个多余的接口。所以在儿子的运营模式下,老父亲的 Work 接口需要重新分配,以工序的角度分配,而不是以完成一个布娃娃的角度分配。总共有 4 个工序:扎辫子、穿衣服、包装入箱、打标签,我们需要定义 4 个接口,让员工去实现各自负责的工序接口。代码如下


interface Hair {
    void hairBraiding();
}

interface Dress {
    void getDressed();
}

interface Box {
    void packingIntoTheBox();
}

interface Tag {
    void makeTag();
}

/**
 * 李大姨给布娃娃扎辫子快
 */
class LiAunt3 implements Hair {

    @Override
    public void hairBraiding() {
        System.out.println("李大姨给布娃娃扎辫子");
    }
}

/**
 * 王大妈给布娃娃穿衣服快
 */
class WangMather3 implements Dress{

    @Override
    public void getDressed() {
        System.out.println("王大妈给布娃娃穿衣服");
    }

}

/**
 * 陈大叔包装快
 */
class ChenUncle implements Box {

    @Override
    public void packingIntoTheBox() {
        System.out.println("陈大叔给布娃娃装箱");
    }
}

/**
 * 黄大姐贴标签快
 */
class HuangSister implements Tag {

    @Override
    public void makeTag() {
        System.out.println("黄大姐给箱子打标签");
    }
}

// 测试代码
LiAunt3 liAunt3 = new LiAunt3();
WangMather3 wangMather3 = new WangMather3();
ChenUncle chenUncle = new ChenUncle();
HuangSister huangSister = new HuangSister();
liAunt3.hairBraiding();
wangMather3.getDressed();
chenUncle.packingIntoTheBox();
huangSister.makeTag();

这段代码看起来就很清晰了,在儿子的运营模式下,大家都是只做一道工序,这样子实现就非常合理。看了这个过程,你理解了接口隔离原则了么?再看一看上面的定义:客户端不应该依赖它不需要的接口。闭上眼睛,静默 3 秒,感受一下。
我们也可以回忆一下在工作中编写的代码,是不是有遵守接口隔离原则?在特定的场景下,如果很多类实现了同一个接口,并且都只实现了接口的极少部分方法,这时候很有可能就是接口隔离性不好,就要去分析能不能把方法拆分到不同的接口。

总结

接口隔离原则最最最重要一点就是要根据实际情况,具体业务具体分析,不能犯了上面说到的错误:在老父亲的运营模式下,按儿子的工序划分接口去实现,那样子会得不偿失。

参考资料:《大话设计模式》、《Java设计模式》、《设计模式之禅》、《研磨设计模式》、《Head First 设计模式》

希望文章对您有所帮助,设计模式系列会持续更新,感兴趣的同学可以关注公众号,第一时间获取文章推送阅读,也可以一起交流,交个朋友。

公众号之设计模式系列文章

公众号
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容