面向对像六大设计原则

        一、单一职责原则

              单一职责原则,这是六大原则中相对好理解的一个原则。

         从字面上意思我们就已经可以理解个大概,没错,这个原则讲的就是说在OO中,我们每个类必须做到单一职责。职责,什么意思呢?我们都知道,类具有行为和属性,他是对象的抽象,每个类都会具有某一种职责,完成相应的功能。而单一职责原则强调的就是每个类都必须有且只有一个职责,比如类A,他有且只能有一个职责P1功能,一个boy类,他有且只有一个职责,就是描述boy类的行为和属性,比如说girl和boy都会运动,boy类应该只描述boy的运动行为,gril应该描述gril的运动行为,而不应该将两个行为绑定在一起(除非用接口,这就不属于我们讨论的范围了。)

  class boy{
	  public void athletics(){
		System.out.println("男孩运动。。");
	  }
  }
  class girl{
	  public void athletics(){
		  System.out.println("女孩运动。。");
	  }
  }

而很多开发者为了简单,不顾及单一职责原则,都喜欢这么写。

  class Person{
	  public void athletics(String sex){
		  if("男孩".equals(sex)){
		System.out.println("男孩运动。。");
	  }else if("女孩".equals(sex)){
		  System.out.println("女孩运动。。");
	  }
  }

       这样写确实是相对来讲简单了多。但是维护起来就变得麻烦了,如果只是简单的功能,比如这里只有一个功能,那还好,那想一下,如果这个类有很多功能呢?这就让一个person类执行了很多不是属于这个类的功能。万一要修改代码,就会使得这个类的维护变得极其麻烦。比如职责扩散,男孩的运动分出了很多,篮球,排球,等等。那就必须修改这一整个方法了,这一不小心就可能会导致女孩运动这部分代码的异常。增大了维护难度。

遵循单一职责原的优点有:
      可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
      提高类的可读性,提高系统的可维护性;
      变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功   能的影响。
      需要说明的一点是单一职责原则不只是面向对象编程思想所特有的,只要是模块化的程序设计,都适用单一职责   原则。

     二、里氏替换原则

      里氏替换原则主要是针对继承,其核心就是:父类已经实现的方法,子类不要去重写!

        继承包含这样一层含义:父类中凡是已经实现好的方法(相对于抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。
      继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能会产生故障。

     那么可能会有开发者会问了,既然不要去重写了,那继承的意义又何在呢?!是的,继承一个类,就是为了复用父类的方法和重写父类的抽象方法!

     同样的,我们用代码来表示一下。

     例如,我们有一个类A实现了两数相减的功能

     

class A{  
    public int func1(int a, int b){  
        return a-b;  
    }  
}  
  
public class Client{  
    public static void main(String[] args){  
        A a = new A();  
        System.out.println("100-50="+a.func1(100, 50));  
        System.out.println("100-80="+a.func1(100, 80));  
    }  
}  
运行结果为:

    100-50=50

    100-80=20

后来,我们需要增加一个新的功能:完成两数相加,然后再与100求和,由类B来负责。即类B需要完成两个功能:两数相减;两数相加在与100求和

由于A类已经实现了两数相减,所以我们只需要重写一个类B来继承类A,并且增加一个两数相加再与100求和的方法就行,因此。代码我们可能会这样写

class B extends A{  
    public int func1(int a, int b){  
        return a+b;  
    }  
      
    public int func2(int a, int b){  
        return func1(a,b)+100;  
    }  
}  
  
public class Client{  
    public static void main(String[] args){  
        B b = new B();  
        System.out.println("100-50="+b.func1(100, 50));  
        System.out.println("100-80="+b.func1(100, 80));  
        System.out.println("100+20+100="+b.func2(100, 20));  
    }  
}  

运行结果为:

    100-50=150

    100-80=120

      100+20+100=220
       我们发现,由于开发者一个不小心,复写了父类的方法,导致了程序的出现了不可预计的错误,可能有开发者这是由于命名的问题,如果父类命名好了,子类怎么还会随意去复写实现的内容呢。可问题是,这个简单的类我们可以解释为命名的问题,可是你能保证程序中所有的方法命名完全无误吗?这个程序的所有开发者都有良好的命名规范吗?所以,为了避免类似的问题出现,只能尽量不要复写父类已实现的方法,

       

三、依赖倒置原则

  定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。 而所谓抽象,在java中的体现就是接口                和抽象类。
     下面,我们就来捋一捋这定义
      问题由来:有一类A依赖类B,后来需要改变了,需要依赖类C,而此时的只能修改类A的代码,类B和类C只是底层,负责原子操作,而类A作为高层,实现了很多复杂的业务逻辑,如果改动类A的代码,则会带来极大的错误风险。这里,就是依赖倒置原则的实现场景之一了。
     解决方案:高层模块类A不要依赖于底层模块类B和类C,改成依赖于接口I,而类B和类C则实现接口I,这样利用接口作为中间件将连接高层模块类A和底层模块类B和类C,这样将会极大地降低了需求改变带来的风险。
     下面以例子作为讲解:
     

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值