先了解UML相关知识
UML类图
+ 表示public
- 表示privae
# 表示protected
~ 表示defualt
下划线 表示static
斜体 表示abstract
开闭原则:对扩展开放,对修改闭合。
// 1.首先创建一个接口ICourse
public interface ICourse {
Integer getid();
String getName();
Double getPrice();
}
// 2.该接口的实现类
public class JavaCourse implements ICourse {
Integer mId;
String mName;
Double mPrice;
public JavaCourse(Integer id, String name, Double price) {
this.mId = id;
this.mName = name;
this.mPrice = price;
}
@Override
public Integer getid() {
return mId;
}
@Override
public String getName() {
return mName;
}
@Override
public Double getPrice() {
return mPrice;
}
}
// 3.调用实现类
ICourse javaCourse= new JavaCourse(98,"Java入门课程",288d);
String r="id="+javaCourse.getid()+";name="+javaCourse.getName()+";原价="+javaCourse.getPrice();
System.out.println(r);
// 4.输出结果
id=98;name=Java入门;原价=288.0
上面是基本操作,现在假设有这么个需求,过节做活动,课程打折,八折,怎么实现?那不是很简单,直接将实现类里面的方法改一下,原价*0.8:
public Double getPrice() {
return mPrice * 0.8;
}
这确实达到了要求,但是如果还要显示原价呢,原价是多少,如果把打八折后的结果除以0.8得到原价,那也太麻烦了。再考虑一下,如果还有其他类实现了JavaCourse类,现在修改了JavaCourse类的getPrice方法,那么其子类全部都改了,还不知道有多大的影响。有人说,我的类少,我可以改,吭哧吭哧改一下,也能实现。是的,没错,但是如果现在有开闭原则,能使代码更优雅,方便你我他,何乐不为呢。
//新建一个类,继承JavaCourse类,并且增加一个方法getDiscountPrice获取折后价
public class JavaDiscountCourse extends JavaCourse {
public JavaDiscountCourse(Integer mId, String mName, Double mPrice) {
super(mId, mName, mPrice);
}
public Double getDiscountPrice(){
return super.getPrice()*0.8;
}
}
//调用
ICourse iCourse= new JavaDiscountCourse(98,"Java入门",288d);
JavaDiscountCourse javaCourse= (JavaDiscountCourse) iCourse;
String r="id="+javaCourse.getid()+";name="+javaCourse.getName()+";原价="+javaCourse.getPrice()
+";折后价:"+javaCourse.getDiscountPrice();
System.out.println(r);
//输出结果
id=98;name=Java入门;原价=288.0;折后价:230.4
这样通过修改实现继承子类(对扩展开放),不修改基类或接口(对修改闭合)来符合开闭原则。
上面这张图是UML的类图,在Android studio安装SimpleUMLCE插件,重启后右击文件夹,生成类图。
依赖倒置原则
//新建一个类
public class StudyCourse {
public void studyJavaCourse(){
System.out.println("学习JAVA课程");
}
public void studyAndroidCourse(){
System.out.println("学习Android课程");
}
}
//调用
StudyCourse studyCourse=new StudyCourse();
studyCourse.studyJavaCourse();
studyCourse.studyAndroidCourse();
//输出结果
学习JAVA课程
学习Android课程
那么问题来了,现在如果想添加一个“学习iOS"的方法,直接在StudyCourse类里添加方法的话,这就是面向实现编程。那么此实现类会经常修改,扩展性较差。 下面看看依赖倒置原则下的实现。
//新建一个接口
public interface ICourse {
void studyCourse();
}
//实现该接口的类
public class StudyJavaCourse implements ICourse{
@Override
public void studyCourse() {
System.out.println("学习JAVA课程");
}
}
//实现该接口的类
public class StudyAndroidCourse implements ICourse {
@Override
public void studyCourse() {
System.out.println("学习Android课程");
}
}
public class StudyCourse {
public void studyMyCourse(ICourse iCourse){
iCourse.studyCourse();
}
}
//调用
StudyCourse studyCourse=new StudyCourse();
studyCourse.studyMyCourse(new StudyJavaCourse());
studyCourse.studyMyCourse(new StudyAndroidCourse());
//结果
学习JAVA课程
学习Android课程
上面的实现看起来麻烦很多,多写了很多代码,那这样带来的好处是什么呢?如果想添加一个“学习iOS"的方法,新建一个类实现ICourse接口里面的方法,这样面向接口编程,而不是面向实现类StudyCourse编程。StudyCourse类与StudyJavaCourse实现类解耦,StudyCourse类与接口ICourse耦合。依赖倒置原则的核心就是面向抽象(抽象类或者接口)编程。
单一职责原则
//新建一个类Bird
public class Bird {
public void move(String name){
if ("鸵鸟".equals(name)){
System.out.println(name+"用脚走");
}
else {
System.out.println(name+"用翅膀飞");
}
}
}
//调用
Bird bird=new Bird();
bird.move("大雁");
bird.move("鸵鸟");
//结果
大雁用翅膀飞
鸵鸟用脚走
现在如果要添加其他鸟类,继续加 if 判断,如果判断的逻辑复杂,很容易出错。下面试试单一职责原则。
//新建一个类
public class FlyBird {
public void move(String name){
System.out.println(name+"用翅膀飞");
}
}
//新建一个类
public class WalkBird {
public void move(String name){
System.out.println(name+"用脚走");
}
}
//调用
FlyBird flyBird=new FlyBird();
flyBird.move("大雁");
WalkBird walkBird=new WalkBird();
walkBird.move("鸵鸟");
//结果
大雁用翅膀飞
鸵鸟用脚走
对于类而言,使用单一职责原则,可能导致类的爆炸,可以酌情使用。反而对于方法而言,尽量使用单一职责原则。
接口隔离原则
//新建一个接口,声明三个方法
public interface IAnimalAction {
void eat();
void fly();
void swim();
}
//新建实现类,实现该接口
public class Dog implements IAnimalAction {
@Override
public void eat() {
}
@Override
public void fly() {
}
@Override
public void swim() {
}
}
//新建实现类,实现该接口
public class Bird implements IAnimalAction {
@Override
public void eat() {
}
@Override
public void fly() {
}
@Override
public void swim() {
}
}
实现类Dog有eat方法,有swim方法,但是没有fly方法。实现类Bird有eat方法,不一定有fly方法,不一定有swim方法。下面是接口隔离原则的实现。
//新建接口
public interface IEatAction {
void eat();
}
//新建接口
public interface IFlyAction {
void fly();
}
//新建接口
public interface ISwimAction {
void swim();
}
//Dog类有eat方法,有swim方法,因此只实现IEatAction,ISwimAction这两接口
public class Dog implements IEatAction,ISwimAction {
@Override
public void eat() {
}
@Override
public void swim() {
}
}
//Bird只有eat方法,只实现IEatAction接口。
public class Bird implements IEatAction {
@Override
public void eat() {
}
}