白话设计模式六大原则

作者: ed407c8602e0 | 来源:发表于2016-05-04 10:50 被阅读7405次

前言

不管你是一个android程序员还是ios,后台程序员,一个好的程序员,不是只会埋头敲代码可以造就的,有时候抬头思考肿么把以后的代码写的更好更有价值。设计模式是一种思考肿么构造代码的方法。今天想结合例子谈谈设计模式的六大基本原则。希望能简单点把问题说清楚,避免高大上的定义,虚无缥缈的遣词造句。


1

单一职责原则

一开始我需要一只会吃吃喝喝的宠物,于是我写了

public class Animal {
    public void eat() {
        Log.i("", "eat");
    }

    public void drink() {
        Log.i("", "drink");
    }
}

一个领养的方法

public class Host {
    public void adopt(Dog dog){
        Log.i("", "i get dog");
    }
}

然后我发现要区分下狗和猫的吃喝,我改

public class Animal {
    public void eat(String kind) {
        if (kind.equals("cat")) Log.i("", "吃鱼");
        if (kind.equals("dog")) Log.i("", "吃骨头");
    }

    public void drink(String kind) {
        if (kind.equals("cat")) Log.i("", "喝鱼汤");
        if (kind.equals("dog")) Log.i("", "喝骨头汤");
    }
}

最后我发现鸡,鸭,鹅。。。都要加进来,我要写多少if,狗带boy。。。我不如把每种动物各自建个类,各自负责自己的吃喝,来一个加一个岂不是happy。于是默默记住

单一职责原则:不要存在多于一个导致类变更的原因

2

里氏替换原则

于是我新建了一个类Dog继承了开始的时候的Animal,至于为什么要继承。。。来源于直觉。。。animal>dog。。。包含关系不是吗?

public class Dog extends Animal{
    public void eat() {
        Log.i("", "吃骨头");
    }

    public void drink() {
        Log.i("", "喝骨头汤");
    }
}

写完了以后发现有点不对劲,貌似违反了

里氏替换原则:子类可以扩展父类的功能,但不能改变父类原有的功能。

我这样一写如果把用到Animal的地方换成Dog,所有的动物都变成吃骨头了。

3

依赖倒置原则

既然继承不能用了,领养的方法出现了难题,我总不能

public void adopt(Dog dog){
    Log.i("", "i get dog");
}

public void adopt(Cat cat){
    Log.i("", "i get cat");
}

.....无数鸡,鸭,鹅方法飞过......

要是真这样估计累死。于是,我想到了接口

public interface Animal {
    public void eat();

    public void drink();
}
public class Dog implements Animal{
    public void eat() {
        Log.i("", "吃骨头");
    }

    public void drink() {
        Log.i("", "喝骨头汤");
    }
}

完美。契合了面向接口编程,而且符合

依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象

领养方法做为高层模块没有直接依赖猫猫狗狗等低层模块,依赖了其抽象,扩展性棒棒的。

4

接口隔离原则

然后发现猫有爬树的技能,狗有汪汪的神级,于是我加了

public interface Animal {
    public void eat();

    public void drink();

    //猫爬树
    public void climbTree();

    //狗汪汪
    public void yell();
}

于是狗变成

public class Dog implements Animal{
    public void eat() {
        Log.i("", "吃骨头");
    }

    public void drink() {
        Log.i("", "喝骨头汤");
    }

    @Override
    public void climbTree() {
        
    }

    @Override
    public void yell() {
        Log.i("", "汪汪");
    }
}

由于狗不会爬树,所以爬树的方法空着。转而一想这样不行,狗还不会飞,不会。。。。等引入其他大量动物,岂不是有大量的空方法?

接口隔离原则:客户端不应该被强迫地依赖那些根本用不上的方法

我只好把接口拆开,用组合搞定,组合是比较推荐的方式。

public interface Animal {
    public void eat();

    public void drink();
}
public interface Yell {
    //狗汪汪
    public void yell();
}
public class Dog implements Animal, Yell{
    public void eat() {
        Log.i("", "吃骨头");
    }

    public void drink() {
        Log.i("", "喝骨头汤");
    }

    @Override
    public void yell() {
        Log.i("", "汪汪");
    }
}

这样狗还有其他技能也可以实现其他接口,当然其他动物要是有相同的技能可以实现相同的接口。关键是没有空方法了,哈哈。

5

迪米特原则

防疫站需要每个宠物的信息,这时候需要一个EpidemicStation对象。如何获取宠物信息有2种方式

  • 通过宠物的主人,EpidemicStation早已有了Host对象,而Host中有一系列关于宠物(Animal)的方法
  • 直接new一个宠物的对象,获取相关信息

我们肯定直接会选择第一种。。。直觉是可以少建个对象。。。早说了我就是这种偷懒的程序猿。。。然而莫名的契合了迪米特法则

迪米特法则:一个对象应该对其他对象保持最少的了解

Host只需要对Animal对象保持关注,而EpidemicStation只需要对Host对象保持关注。EpidemicStation对象不需要了解Animal。感觉直接点就是,在一个类中应该少出现其他类,其实这也是解耦的需要。

6

开闭原则

直接抛出定义吧

开闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭

感觉这个原则容易看懂,最难做到。白话就是不要改你以前写的代码,你应该加一些代码去扩展原来的功能,来实现新的需求。好处很好理解,改原来的代码很容易影响原来的功能,特别是接手别人的代码,不理解原先业务场景的情况下。关于‘不要动之前的代码’感觉槽点无数啊,看自己写的代码想吐有木有?别人的代码简直...?之前哪里会想到会有这种鬼需求?.......


后记

绞尽脑汁把原则说清楚。感觉原则性的东西应该是简单易遵守的,重要的还是在以后的编程中实践,所以下手写代码前再看看本文?想想六个原则?如果有用欢迎关注我,欢迎点喜欢。。。

推荐

一个神奇的网站
http://androidcat.com/

关注我(微信扫一扫)

相关文章

  • 设计模式

    设计模式六大原则[设计模式六大原则(1):单一职责原则][设计模式六大原则(2):里氏替换原则][设计模式六大原则...

  • 设计模式-六大原则

    转载自 设计模式六大原则 目录:- 设计模式六大原则(1):单一职责原则- 设计模式六大原则(2):里氏替换原则-...

  • 设计模式六大原则

    目录: 设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒...

  • 设计模式6大原则

    目录: 设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒...

  • 设计原则之6大原则

    目录:设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒置...

  • 设计模式(二):六大原则

    参考:设计模式六大原则简书-快速理解-设计模式六大原则注意:IoC 也属于设计模式吧。 设计模式六大原则(1):单...

  • 设计模式 - 六大原则

    Reference 快速理解-设计模式六大原则 设计模式的六大原则 设计模式之六大原则作者:海子出处:http:/...

  • 无标题文章

    设计模式之六大原则(转载) 设计模式之六大原则(转载) 关于设计模式的六大设计原则的资料网上很多,但是很多地方解释...

  • 设计模式六大原则

    设计模式之六大原则(转载) 关于设计模式的六大设计原则的资料网上很多...

  • Mr.Li--python-Linux-设计模式

    设计模式: 设计模式六大原则(1): 单一职责原则:一个类只负责一项职责 设计模式六大原则(2): 里氏替换原则:...

网友评论

  • 付凯强:不错,加油。
  • 檀文渊:六大原则贯穿所有设计模式
    ed407c8602e0: @檀文渊 相当于武学总纲
  • g才华横溢:学习了
    ed407c8602e0:@鑫强 ♪(^∇^*)
  • Pr_Chen:总结得不错,学习了.
    ed407c8602e0:@Pr_Chen :smile:
  • 简单的土豆: 感觉里氏代换和我理解的不一样啊,下面是我理解中的里氏代换。

    里氏代换原则(Liskov Substitution Principle, LSP):所有引用基类(父类)的地方必须能透明地使用其子类的对象。

    里氏代换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。例如:我喜欢动物,那我一定喜欢狗,因为狗是动物的子类;但是我喜欢狗,不能据此断定我喜欢动物,因为我并不喜欢老鼠,虽然它也是动物。
    简单的土豆:@wolearn的小舟 里氏代换原则就是要告诉我们要面向抽象类、接口编程,在定义类型时尽量用父类,在程序运行时再确定具体子类,以便实现开闭原则。
    简单的土豆:@wolearn的小舟 是可以Override父类方法的,说白了就是一个方法允许传入一个父类型(可以是class 或 interface)实例可以很好的工作的话,那么传入其子类型也应能很好地工作。
    ed407c8602e0:@酸辣土豆芽 是的,依据你的例子,“我喜欢动物,那我一定喜欢狗”,那在喜欢动物的地方用喜欢狗替换是否缩小了适用范围。比如原来用动物的地方,其实是喜欢猫的,但是不写喜欢猫写成喜欢动物没问题,你用狗来替换就出问题了。而里氏的本意是不改变父功能,扩充父功能
  • 3035cec932c2:虽然不是搞ios和android,但是看懂了这思想,还是感觉楼主屌屌的
    3035cec932c2:@wolearn的小舟 是的,而且思想很重要
    ed407c8602e0:@Prince丶Man 编程思想通用
  • Runwuwusheng:喜欢
    ed407c8602e0:@Runwuwusheng :smiley: :smiley:
  • cyrano66:很不错 简洁明了
    ed407c8602e0:@cyrano66 :smile:
  • Echo剑心:受教,正好现在在学习设计模式
    ed407c8602e0:@Echo剑心 :blush:
  • 简单的土豆:不错
    ed407c8602e0:@酸辣土豆芽 :smiley:
  • acc352b11f48:很棒 受教了!
    ed407c8602e0:@ximcooper :smile:
  • 28f76471df61:大写的 屌 !
  • 山猫0131:运用到实际工作中并不容易,实际情况比这复杂的多。
    无夜之星辰:领悟并灵活运用真的很难
    ed407c8602e0:@山猫0131 是的,慢慢来

本文标题:白话设计模式六大原则

本文链接:https://www.haomeiwen.com/subject/qpzlrttx.html