zoukankan      html  css  js  c++  java
  • 为什么要用设计模式?先看看6大原则(一)

      引言                                       

      本人不怎么喜欢看书, 因为我看书一目十行, 看了就忘, 所以我这边一边看左老师的, 一边抄, 增加自己的记忆力

      这是左老哥的 http://www.cnblogs.com/zuoxiaolong/p/pattern1.html

      直接进入正题, 相信大家入了这一行, 几乎都忙的一笔, 但还是想要在闲时充下电. 我老想给自己充电, 时间也不少, 但是呢, 不玩上两把游戏不过瘾, 让大脑休息休息, 但是一玩游戏就停不下来了, 要是我把玩游戏的精神来学习java, 这句话怎么这么耳熟, 不管了, 先读一读设计模式. 

      ps 上面都是扯淡

      学习设计模式, 就是为了让我们显着更加专业, 是的, 我们是专业coder

      主体

      学习设计模式之前, 我们需要先了解六大原则, 这原则看着很有道理

    ①单一原则:

        意思: 只做一件事.

        我用个伪代码表达一下

    //计算文件中的
    class Calculator {
       //相加  
      public int add() throws NumberFormatException, IOException{ File file = new File("E:/data.txt"); BufferedReader br = new BufferedReader(new FileReader(file)); int a = Integer.valueOf(br.readLine()); int b = Integer.valueOf(br.readLine()); return a+b; }
     }

        要是谁封装了这么一个类, 然后你用了, 卧槽什么怎么只有加法, 没有减法 乘法, 你然后是不是要 copy 一下 ,把+ 号改为其他符号 . 

        q:这个类中哪里违反了单一原则呢?

        梳理一下, 我们用这个计算类是为什么干什么, 计算文本中的和

        引申一下, 实际的操作步骤:

                     ① 获取文件内容

                     ② 计算返回值        

        这个类同时拥有两个职责

        q:这个类还存在什么问题?

        在开发初期, 我们很有可能为了快速, 进行大量的copy, 这样就导致了很多的代码重复, 这样可能我们为了书写一个相减或相乘的方法, 来copy 加法中的代码进行修改

      下面我们需要把上面的代码修改一下

    //获取文件内容类
    class Reader{
    
        int a,b;
    
        public Reader(String path)throws Exception{
         
        BufferedReader br = new BufferedReader(new FileReader(new File(path)));
          a= Integer.valueOf(br.readLine);          
          b= Integer.valueOf(br.readLine);          
        }
        
        int getA(){
            return a;
        }
    
             
        int getB(){
            return b;
        }  
    }
    
    //单独的计算类
    
    class Calculator{
        
        int add(int , int b){
        return a+b;
    }    
    
        int subtract(int , int b){
        return a-b;
    }        
    }

        这样简单明朗,意思深刻 ,当然这些都是我抄的大神的, 有时候没有必要自己写一些代码, 跟着前辈走, 带你少走很多弯路, 有时候总是走自己的路, 尽管得到的更多, 但是并不是每个人都是这样的, 我是前者, 我明白自己的短板. 

        

    ②里氏替换原则

       意思: 子类应该可以替换掉父类并且正常工作

         子类一般不该重写父类的方法, 因为父类的方法一般都是对外公开的.

       但是在实际开发当中, 我们可能为了便利, 经常重写父类的方法, 这样就导致的子类和父类作了不同的功能,

       下面我们用代码来描述一下:

    //父类
    class FatherClass{
    
        public void eat(){
         System.out.println("我爱吃米饭");
    
        }  
    
    
    }
     
    //子类
    class SonClass extends FatherClass{ void eat(){ System.out.println("我不爱吃米饭"); } } class SomeoneClass { @Test public void runLiSi(){ FatherClass fc = new FatherClass(); SonClass sc = new SonClass(); fc.eat(); sc.eat(); } }

        上面这个例子, 父类和子类做同样的事, 但是结果确实相反的

        这个原则是在约束我们, 往往出现这种情况的时候, 我们需要考虑一下能不能, 效果如何. 

    ③接口隔离原则(接口最小化原则) 

       开发中中 我们经常发现 我们在实现一个接口的同时, 有很多方法都是空的

        直接上代码

    //手机接口
    public interface BaseMobile {
        
           public void call();//打电话
    
           public void sendSms();//发短信
    
           public void playBird();//玩游戏  
    }

          只要是手机那就应该有打电话发短信的功能, 但是玩游戏的功能并不一定是每个手机都有的

              所以我们可以先让去掉 玩游戏 这个接口 最小化这个接口

    //修改后的代码
    
    public interface BaseMobile {
        
        public void call();
    
        public void sendSms();  
    
    }
    
    //适配器
    
    public interface IOSMobile extends BaseMobile{
    
        public void playBird();
    
    }

         这样, 就很清晰的理解接口最小化原则,

         但是凡事都有特例,

         不需要发短信功能的手机存在吗, 很显然存在啊. 同样的, 时代发展的很快, 手机的基本功能也在变迁, 就像这样是个手机应该就能上网之类的功能

         ps:写到这里, 我明显感觉我的思考问题的方式在发生着改变, 我们的代码, 应该遵循的一些规范, 往往在人们的生活方式改变的同时改变着, 代码离不开生活, 美好的生活由代码构成, 在今后的社会, 有可能我们的代码就像是科学一样, 人人都应该了解她, 学习她. 

    ④依赖倒置原则    

        高层模块不应该依赖与底层模块, 二者都应该依赖于抽象, 抽象不应该依赖于细节, 细节应该依赖于抽象

        这句话意思就是, 不管你是北京人,还是北京朝阳群众, 你都是中国人, 这么理解就没错了. 实际上, 我还是感觉上句话好理解一点.

        下面我们直接用代码来表示一下

    //抽象 人
    public interface People{
        
        void myInfo();//自我介绍
        void canDo();//能做什么
    }
    
    //中国人 
    public class China:People{
        public void myInfo(){
          System.out.println("我是中国人");  
      }
        void canDo(){
         System.out.println("我会code,搬砖,修车,开车,滑稽");  
    }
    }   
    
    //美国人
    public class America:People{
        public void myInfo(){
          System.out.println("我是美国人");  
      }
        void canDo(){
         System.out.println("我会code,mygod,yea,aye,huhuh");  
    }
    }   
    //高层 
    public class PeopleInfo{
    
    private People people;
    
    public PeopleInfo(People people){
        this.people =people;
    }
     public void myInfo(){
          people.myInfo();
      }
        void canDo(){
         people.canDo();
    }
    
    }

      现在PeopleInfo这个类依赖于People, 而具体方法不会影响PeopleInfo , 只要改变实现People即可 ,也就是细节依赖于抽象

      并且 PeopleInfo 不依赖于China和America, 也就是依赖关系被倒置了

      这里我解释下可能有的同学不是很清楚其中的利害   依赖倒置

      PeopleInfo 依赖于 People  ,当我们需要使用PeopleInfo做某些事情的时候, 这时需要注入China或其他实现类, 但是PeopleInfo并不依赖China,

    PeopleInfo只依赖People .

      想象一下, 我们使用PeopleInfo, 注入China,使用myInfo()的结果:我是china. 注入America,使用myInfo()的结果:我是America. 

          q:说明PeopleInfo不依赖 China 和America ,但是怎么能调用它们的方法呢?

      反过来想下, 我想要使用China myInfo()方法 有两个方法

             第一种 直接new 是不是有点粗暴

             第二种 把China 注入PeopleInfo  专业code啊

         第二种 China反而依赖于PeopleInfo 依赖就这么反转了, 这是我目前的理解,有问题, 大家可以指出来

     

    ⑤迪米特原则

        最小知道原则, 一个类尽量不应该知道其他类太多的东西,不要有太多的接触

        大白话, 就是一个类不应该依赖其他的类太多细节, 其他类不应该对外提供太多细节, 要高内聚, 低耦合

    先来个不符合这个原则的

    //低内聚
    public class LowCohesion{
    
       private String name;
    
       private int age;
    
       private boolean openMouth = false;
        
       public LowCohesion(String name, int age){
    
               this.name = name;
               this.age = age;
      }
    
        
      public void setOpenMouth(boolean boo){
    
         this.openMouth = boo;
     }
      public saySelf(){
         if(openMouth){
            System.out.println("大家好,我叫"+name+", 今年"+age+"了");
        }else{
            System.out.println("......");
        }
         
     }
    
    }
    
    //客户端
    
    public class client{
    
           public static void main(String[] args) throws Exception {
            LowCohesion lc= new LowCohesion("老哥",26);//来了个老哥
            lc.setOpenMouth(true);//老哥张嘴
            lc.saySelf();//老哥说话
         
        }
    
    }

        假设我们是面试官, 来个人,我们一般只需要让人自我介绍 , 也就是 saySelf ,这个例子里面我们需要openMouth,这就是 类不应该依赖其他的类太多细节

        这个动作可以是外驱的 但是这个细节完全没必要暴露出去, 我们要的是自我介绍, 而不是 先我准许你说话 , 然后你可以自我介绍, saySelf这个动作应该内置 openMouth ,   也就是 其他类不应该对外提供太多细节

        我的表达可能不是很准确, 迪米特原则,我的理解是双向约束的规则, 其中主要是针对 类的内聚性

    ⑥开闭原则 

        对修改关闭, 对扩展开发.

        在实际开发中, 我们由于各种场景需求, 需要修改大量的原有的代码, 很多项目都是非常的赶, 扩展性, 项目有二开就有扩展性

        有时候我感觉自己可以掌控一方, 但是实际真的什么都不懂, 再次感觉前辈们, 我会坚持下去

        

  • 相关阅读:
    解决Java版CKFinder无法显示缩略图问题
    python视频教程大全
    关于Linux vi命令 vi命令一览表
    Python快速教程
    Linux的概念与体系
    每天一个linux命令目录
    每天一个linux命令(31): /etc/group文件详解
    每天一个linux命令(30): chown命令
    每天一个linux命令(29):chgrp命令
    十大Material Design开源项目
  • 原文地址:https://www.cnblogs.com/denghailei/p/6214604.html
Copyright © 2011-2022 走看看