美文网首页程序员
六大设计原则 笔记

六大设计原则 笔记

作者: 王黎聪 | 来源:发表于2018-03-06 11:49 被阅读32次

首先感谢宗传奇大神 送了我一本《设计模式之禅》,春节期间把这本书快速的读了一遍。
很久前对设计原则有过学习,但并没有去在意。最近几天写代码,发现写代码的时候脑子里会冒出这用的是‘开闭原则’,或 准备写代码的 问一下自己会用到什么原则。虽然设计原则不能帮助你现实任何业务,也不能明显的减少代码的开发量,但是很神奇。说它是禅,一点都不过分。
由于领悟尚浅,方便回味,自己写了简洁的案例;同时也希望各位大神,建议指导;


  • 开闭原则(Open-Closed Principle, OCP)

一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

重构前,只要节目有变就要改春晚代码

    //春晚演节目  (重构前)
    public void chunWan(String name){
        if("贾玲".equals(name)){
            JiaLing jiaLing=new JiaLing();
            jiaLing.xiaoPin();
        }else if("王菲".equals(name)){
            Wangfei wangfei=new Wangfei();
            wangfei.changGe();
        }
    }

重构后,让春晚演节目更灵活。

    //春晚演节目  (重构后)
    public void chunWan(YanYuan yanYuan){
        yanYuan.biaoYan();
    }

    //抽象出一个演员抽象类,添加一个biaoYan抽象方法.
    public abstract class YanYuan {
        public abstract void biaoYan();
    }

    //让贾玲继承 演员抽象类  并实现biaoYan抽象方法.
    public class JiaLing extends YanYuan{
        @Override
        public void biaoYan() {
            System.out.println("贾玲开始小品表演");
        }
    }
    //王菲亦如此,实现表演唱歌. 从此所有人继承演员就可以上春晚了!
...

  • 里氏替换原则(Open-Closed Principle, OCP)

    子类可以扩展父类的功能,但不能改变父类原有的功能。所有引用父类的地方必须能透明地使用其子类的对象。
重构前,功能混乱没有约束,容易出错,弄不好就挂了。

    public static void main(String[] args) {
        Guo guo = new PingDiGuo();
        //找个 锅 来 烹饪
        zuoFan(guo);
        //结果 拿锅拍人去了
    
    }
    //传入锅来做饭
    public static void zuoFan(Guo guo){
        guo.function();
    }
    //可以做饭的锅类
    public static class Guo{
        public void function(){
            System.out.println("我来烹饪了");
        }
    }
    //一只平底锅
    public static class PingDiGuo extends Guo{
        public void function(){
            System.out.println("发现平底锅,可以杀人越货,我要维护世界和平");
        }
    }

重构后,保留锅的本质功能,平底锅特有功能应该独自实现。

    public static void main(String[] args) {
        Guo guo = new PingDiGuo();
        //找个 锅 来 烹饪
        zuoFan(guo);
        //锅的本质功能 被保留
    
    }
    //传入锅来做饭
    public static void zuoFan(Guo guo){
        guo.function();
    }
    //可以做饭的锅类
    public static class Guo{
        public final void function(){
            System.out.println("我来烹饪了");
        }
    }
    //一只平底锅
    public static class PingDiGuo extends Guo{
        public void newFunction(){
            System.out.println("发现平底锅,可以杀人越货,我要维护世界和平");
        }
    }

小结: 子类可以扩展父类的功能,但不能改变父类原有的功能。

里氏替换原则 举例非常困难,简单的总结一下
1:不能重写父类本质的非抽象方法。
2:父类本质功能,不想被重写可以加 final。
3:在子类中增加自己特有的方法。
4:当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
5:当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。


  • 依赖倒置原则(Dependency Inversion Principle, DIP)

高层模块不应该依赖低层模块,两者都应该依赖其抽象。抽象不应该依赖于细节。
细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。

重构前,扩展差,不符合开闭原则。并且功能容易混乱。

    //有个唱歌节目 传进不同的人唱歌
    public void play(People ren){
        ren.changGe();
    }
    //过了一段时间突然有只 鸟 也来节目 唱歌 ,然后节目 扩展 了一个 方法
    public void play(Bird niao){
        niao.changGe();
    }
    //渐渐时间旧了,发现两个问题 ,
    //  1:不是所有的人或鸟都会唱歌;
    //  2:还有其他动物也会唱歌;

重构后,想去参加唱歌节目,就必须实现唱歌,简单清楚。

    //抽象出一个 歌曲类 , 有开始唱的功能;
    public abstract class Song{
        public abstract void play();
    }
    
    // 节目组做了调整 , 需求更明确 , 要求会唱歌的来, 不会唱歌的就不能来
    public void play(Song geQu){
        geQu.play();
    }
    
    //所以 接下来 想去 参加节目的 就必须要会唱歌   (实现Song)


  • 接口隔离原则(Interface Segregation Principle, ISP)

客户端不应该依赖它不需要的接口。类间的依赖关系应该建立在最小的接口上。

重构前,

    //有个演员抽象类 会唱歌  继承了唱歌 功能
    public interface YanYuan extends Song{
        void playSong();
    }
    //节目 邀请 演员 来唱歌
    public void JieMu(YanYuan yanYuan){
        yanYuan.playSong();
    }

重构后,

    //演员抽象类 会唱歌
    public interface YanYuan  {
        void playSong(Song song);
    }
    //节目开始    歌 被演员唱了起来
    public void JieMu(YanYuan yanYuan){
        yanYuan.playSong(getSong());
    }
    
    //接口隔离原则能从很多 维度举例; 拆分细化等;
    //个人看标题的表面意思 理解 更偏向于,接口回调,接口解耦方面....


  • 迪米特法则(Law of Demeter, LoD)

一个软件实体应当尽可能少地与其他实体发生相互作用。

重构前,

    //一个教室类 里面有很多电器
    public class JiaoShi{
        //各种电器
        public KongTiao kongTiao;//空调
        public Deng deng;//灯
        public YinShuiJi yinShuiJi;//饮水机
        ....
    }
    //一个老师类 有检查关闭电源 的方法
    public class Teacher{
        public void jianChaDianYuan(JiaoShi jiaoShi){
            jiaoShi.kongTiao.close();//关空调
            jiaoShi.deng.close();//关灯
            jiaoShi.yinShuiJi.close();//关饮水机
        }
    }
    //老师需要 知道所有电器 并关闭
重构后,

    //一个教室类 里面有很多电器
    public class JiaoShi{
        //各种电器
        public KongTiao kongTiao;//空调
        public Deng deng;//灯
        public YinShuiJi yinShuiJi;//饮水机
        ....
        //一个 开关
        public void closeAll(){
            jiaoShi.kongTiao.close();//关空调
            jiaoShi.deng.close();//关灯
            jiaoShi.yinShuiJi.close();//关饮水机
        }
    }
    
    //一个老师类 只需要知道一个开关即可
    public class Teacher{
        public void jianChaDianYuan(JiaoShi jiaoShi){
            jiaoShi.closeAll();
        }
    }
    
    //还有一个层面的理解: 抽出一个 总闸开关 接口, 有个抽象方法 closeAll(); 
    //只需要传给老师 总闸开关 , 老师调用 总闸开关的closeAll(),就能关闭所有电源
    //然而不需要关心具体关闭什么电器, 这样电器 和 老师 就解耦了


  • 单一职责原则(Single Responsibility Principle, SRP)

一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。

重构前,

    //茶农类, 从前有个很辛苦的 茶农 ,
    public class ChaNong{
        //他要负责种茶叶
        public void zhongCha(){
            System.out.println("种茶,收茶");
        }
        //还需要加工茶叶
        public void jiaGongCha(ChaYe chaYe){
            System.out.println("加工了100盒");
        }
        //然后去集市卖茶
        public void maiCha(ChaYe chaYe){
            System.out.println("成功卖了100盒,收到了很多钱");
        }
    }
重构后,
    
    //加工厂类, 由于茶农辛苦 ,收益底 ,一个很有眼光的人, 开了一家 加工茶叶销售公司
    public  class JiaGongChang{
        //加工茶叶
        private void jiaGongCha(ChaYe chaYe){
            System.out.println("加工了100盒");
        }
        //然后批发茶叶到市场
        public Money maiCha(ChaYe chaYe){
            jiaGongCha(chaYe);
            System.out.println("成功卖了100盒,收到了很多钱");
            ...
            return money;
        }
    }
    
    //茶农类, 从此 茶农 就有了 清闲 的生活
    public class ChaNong{
        //他只负责种茶
        public void zhongCha(){
            System.out.println("劳动最光荣");
        }
    
        //然后去集市卖茶
        public void maiCha(ChaYe chaYe){
            Money money =new JiaGongChang().maiCha(chaYe);
            System.out.println(money);
        }
    }


本文是作者通过再次学习后的理解总结,希望能为大家带来帮助; 谢谢,谢谢宗传奇赠书

推荐链接: 设计模式之六大原则(转载)
推荐链接: 迪米特法则

相关文章

  • 设计模式

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

  • 设计模式-六大原则

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

  • 设计模式六大原则

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

  • 设计模式6大原则

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

  • 设计原则之6大原则

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

  • 设计模式 - 六大原则

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

  • 无标题文章

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

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

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

  • 设计模式六大原则

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

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

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

网友评论

    本文标题:六大设计原则 笔记

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