在使用面向对象的思想进行系统设计时,应遵循面向对象的设计原则,前人总结的7条分别是:单一职责原则、开闭原则、里氏替换原则、依赖注入原则、接口分离原则、迪米特原则和优先使用组合而不是继承原则。
单一职责也就是开发人员经常说的“高内聚低耦合”,也就是说系统中的每一个对象都应该有一个单独的职责,对外只能提供一种功能,引起对象变化的原因也只有一个,所有的设计模式都遵循这一原则。通常一个类的职责越多,导致其变化的因素也就越多。一般情况我们设计类时会把该类有关的操作都组合在一起,这样的结果就是有可能将多个职责聚合到了一起,当这个类的某个职责发生变化时,很难避免其他部分不受影响,最终导致程序的脆弱和僵硬。解决办法就是分耦,将不同职责分别进行封装。
例如用户的属性和用户的行为被放在一个接口中申明,造成业务对象和业务逻辑混在一起,使接口有两种职责。
/*** JavaProject* Created by xian.juanjuan on 2017-7-10 10:59.*/
public interface Ijuanjuan {//身高double getShengao();void setShengao(double height);//体重double getTizhong();void setTizhong(double weight);//吃饭boolean chiFan(boolean hungry);//上班boolean shangBan(boolean flag);
}
分别定义属性和行为接口并分别实现
/*** BO:Bussiness Object*/
public interface IjuanjuanBO{//身高double getShengao();void setShengao(double height);//体重double getTizhong();void setTizhong(double weight);
}
public class JuanjuanBO implements IjuanjuanBO{private double height;private double weight;@Overridepublic double getShengao() {return height;}@Overridepublic double getTizhong() {return weight;}@Overridepublic void setShengao(double height) {this.height = height;}@Overridepublic void setTizhong(double weight) {this.weight = weight;}
}
/*** BL:Business Logic*/
public interface IjuanjuanBL{//吃完上班boolean chiFan(boolean hungry);boolean shangBan(boolean flag);
}
public class JuanjuanBL implements IjuanjuanBL{@Overridepublic boolean chiFan(boolean hungry) {if(hungry){System.out.println("吃大餐。。。");return true;}return false;}@Overridepublic boolean shangBan(boolean flag) {if (flag){System.out.println("上班中。。。");return true;}return false;}
}
这样需要修改用户属性的时候只需要对IjuanjuanBO这个接口进行修改,影响的也只是JuanjuanBO这个类,其余的类不受影响。
SRP原则的好处是消除耦合,减小因需求变化而引起代码僵化的局面。
里氏替换原则的核心思想是:在任何父类出现的地方都可以用他的子类来代替。即同一个继承体系中的对象应该拥有共同的行为特征。也就是说只要父类出现的地方子类就能出现而,且替换为子类不会出现任何错误和异常,但是反过来,子类出现的地方替换为父类很可能就出问题了。
这一原则为良好的继承指定了一个规范:
规范3示例
package com.xianjj.principle;import java.util.Collection;
import java.util.HashMap;
import java.util.Map;/*** JavaProject* Created by xian.juanjuan on 2017-7-10 14:01.*/
public class Father {public Collection say(HashMap hashMap){System.out.println("father 被执行");return hashMap.values();}
}class Son extends Father{public Collection say(Map map) {System.out.println("son 被执行");return map.values();}
}class Home{public static void main(String[] args){invoke();}public static void invoke(){Son son = new Son();HashMap hashMap = new HashMap();son.say(hashMap);Map map = new HashMap<>();son.say(map);Father father = new Father();HashMap hashMap1 = new HashMap();father.say(hashMap1);}
}
执行结果
father 被执行
son 被执行
father 被执行
依赖注入原则的核心思想:要依赖于抽象(抽象类或接口),不要依赖于具体的实现。在应用程序中,所有的类如果使用或依赖于其他类,都应该依赖于这些类的抽象类,而不是具体实现类。要求:开发人员应该针对接口编程
依赖注入原则三点说明:
依赖注入的本质是通过抽象(抽象类或接口是不能实例化)使各个类或者模块之间实现彼此独立,不相互影响,实现模块间的送耦合。
依赖注入的三种实现方式:
例如,涂涂只会煮面条
public class Tutu {//涂涂只会煮面条public void cook(Noodles noodles){noodles.eat();}
}class Noodles{public void eat(){System.out.println("涂涂吃面条");}
}class Eat{public static void main(String[] args){Tutu tutu = new Tutu();Noodles noodles = new Noodles();k(noodles);}
}
涂涂天天吃面条吃腻了,想吃水煮鱼,大闸蟹怎么办呢,于是涂涂开始学习做其他吃的,需要实现Ifood接口。
public class Tutu {public void cook(Ifood ifood){ifood.eat();}
}interface Ifood{public void eat();
}class Noodles implements Ifood{@Overridepublic void eat(){System.out.println("涂涂吃面条");}
}class Rice implements Ifood{@Overridepublic void eat() {System.out.println("涂涂吃米饭");}
}class Eat{public static void main(String[] args){Tutu tutu = new Tutu();//涂涂会煮面条Ifood noodles = new Noodles();k(noodles);//涂涂学会煮米饭Ifood rice = new Rice();k(rice);}
}
煮米饭和煮面条作为两个独立的模块互不影响,实现了松耦合。如果以后涂涂还想吃饺子,只需要实现Ifood接口即可。
接口分离原则的核心思想:不应该强迫客户程序依赖他们不需要的方法。意思就是说:一个接口不需要不需要提供太多的行为,不应该把所有的操作都封装到一个接口中。
这里的接口不仅指interface定义的接口,包含以下两种:
使用接口分离原则的规范:
//定义美女接口
public interface IprettyGirl {void greatLooks();//长相好void greatFigure();//身材好void greatTemperament();//气质佳
}class PrettyGirl implements IprettyGirl{private String name;public PrettyGirl(String name) {this.name = name;}@Overridepublic void greatFigure() {System.out.println(name+":身材非常好");}@Overridepublic void greatLooks() {System.out.println(name+":长相非常好");}@Overridepublic void greatTemperament() {System.out.println(name+":气质非常好");}
}//抽象一个帅哥
abstract class IMan{protected IprettyGirl prettyGirl;public IMan(IprettyGirl prettyGirl) {this.prettyGirl = prettyGirl;}//帅哥开始找美女了public abstract void findGirl();
}class Man extends IMan{public Man(IprettyGirl prettyGirl) {super(prettyGirl);}@Overridepublic void findGirl() {System.out.println("找到美女了。。。");atFigure();atLooks();atTemperament();}
}class Beijing{//在北京找美女public static void main(String[] args){IprettyGirl jiajai = new PrettyGirl("佳佳");IMan man = new Man(jiajai);man.findGirl();}
}
这里有个问题是,接口的划分不是很清晰,有的人认为长相好,身材好的就是美女,有的则认为气质佳的就是美女,所以需要把接口划分的再细致一点,长相好身材好的为一个接口,气质佳的为一个接口,以满足不同人的审美观。
迪米特原则的核心思想是:一个对象应该对其他对象尽可能少的了解。即实现对象之间解耦,弱耦合。例如除了探亲,监狱(类)里的犯人(类内部信息)不应该与外界有接触。他们与外界信息传递是通过狱警(迪米特法则的执行者)来执行。
例如:家人去监狱探亲,对于家人来说只与某个犯人是亲人,家人与其他犯人之间并不认识。家人与监狱之间就是弱耦合。
开闭原则的核心思想:一个对象对扩展开放,对修改关闭。意思是说对类的改动是通过增加代码进行的,而不是改动现有的代码。这就需要借助于抽象和多态,把可能变化的内容抽象出来,从而使抽象的部分相对稳定,具体的实现是可以改变和扩展的。
用一个示例来说明对象的继承与组合:
假如有对象A,实现了a1方法,对象C想扩展A的功能,并给它增加一个新的c11,两种实现方案
继承
class A{public void a1(){System.out.println("now in A.a1");}
}class C extends A{public void c11(){System.out.println("now in C.c11");}
}
对象组合
class C2{//创建A对象的实例A a = new A();public void a1(){// 转调A对象的功能a.a1();}public void c11(){System.out.println("now in C2.c11");}
}
对象组合优点:
摘自:修炼—清华大学出版社,于广编著
本文发布于:2024-01-29 13:01:21,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170650448315467.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |