一、什么是开闭原则
Open-Close Principle,简称OCP,指的是一个软件实体(包括一个模块、类和方法)都应该对修改关闭、对拓展开放,也就是对修改和拓展这两个行为的原则;
在面向对象中,强调的是用抽象构建框架(关闭修改),用实现拓展新功能(开放拓展);
在Java中具体点就是,使用抽象类或接口定义整体系统框架,然后使用子类或具体类去重写抽象类或实现接口相关方法,达到不用修改原来代码就可以拓展新的功能。
二、开闭原则的优点
-
提高软件实体的可复用性
使用抽象构建的框架,那么抽象出来的东西具有很大的共同特性,可以直接拿来复用,避免重复定义或编码。
-
提高软件实体的可拓展性
现有的功能特性不满足未来的需求变化,可基于抽象框架进行拓展新的功能,不修改原来的代码即可完成拓展性。
-
提供软件实体的可维护性
所有的功能特性都是基于抽象框架拓展而成,各个功能特性独立且相互不影响,后期维护目标明确且方便。
三、开闭原则的缺点
面向对象的抽象难度大,如果在刚开始使用抽象构建的框架考虑不全,后期已经拓展了很多功能特性,一旦抽象的基础框架发生变动,下面的拓展部分都有可能受到影响;因此需要很强、很系统的抽象能力把基础框架抽象出来,才能减少后期带来的不必要影响。
四、开闭原则的具体实现
-
需求
识别各种不同的人群信息,并输出。
-
代码实现
person类:基本属性
public class Person {
private Integer id; // 唯一身份ID
private String name; //名字
private String sex; //性别
private String address; //住址
private List<String> interests; //兴趣爱好
private String race; // 种族
private String color; // 肤色
public Person(Integer id, String name, String sex, String address, List<String> interests, String race, String color) {
this.id = id;
this.name = name;
this.sex = sex;
this.address = address;
this.interests = interests;
this.race = race;
this.color = color;
}
}
person接口:抽象对外暴露的方法,只能调用这些方法(对修改关闭)
public interface IPerson {
String getName(); // 获取person的名字
String getColor();// 获取person的肤色
String getRace();// 获取Person的种族
String getSex(); // 获取person的性别
List<String> getAction(); // 获取person具有的行为
}
person抽象类:抽象person的基本特征,可以直接复用
public abstract class AbstractPerson {
public String eat() {
return "eat";
}
public String drink() {
return "drink";
}
public String shit() {
return "shit";
}
}
person具体类:主要是基于person抽象类的拓展功能
第一个拓展person:
public class OnePerson extends AbstractPerson implements IPerson {
private Person person;
public OnePerson(Person person) {
this.person = person;
}
@Override
public String getName() {
return person.getName();
}
@Override
public String getColor() {
return person.getColor();
}
@Override
public String getRace() {
return person.getRace();
}
@Override
public String getSex() {
return person.getSex();
}
@Override
public List<String> getAction() {
List<String> actions = new ArrayList<>();
actions.add(this.eat());
actions.add(this.drink());
actions.add(this.shit());
actions.add(this.work());
return actions;
}
private String work(){
return "work";
}
}
第二个拓展person:
public class TwoPerson extends AbstractPerson implements IPerson {
private Person person;
public TwoPerson(Person person) {
this.person = person;
}
@Override
public String getName() {
return person.getName();
}
@Override
public String getColor() {
return person.getColor();
}
@Override
public String getRace() {
return person.getRace();
}
@Override
public String getSex() {
return person.getSex();
}
@Override
public List<String> getAction() {
List<String> actions = new ArrayList<>();
actions.add(this.eat());
actions.add(this.drink());
actions.add(this.shit());
actions.add(this.play());
return actions;
}
private String play(){
return "play";
}
}
人脸识别类:调用person接口的相关方法
public class FaceRecognition {
public static void printPersonInfo(IPerson person) {
System.out.println("姓名:"+person.getName());
System.out.println("性别:"+person.getSex());
System.out.println("肤色:"+person.getColor());
System.out.println("种族:"+person.getRace());
System.out.println("个人行为:"+person.getAction().toString());
}
}
测试类test:测试类
public class Test {
public static void main(String[] args) {
Person person= new Person(1,"huahua","man","aaa.",new ArrayList<>(),"china","yellow");
OnePerson onePerson = new OnePerson(person);
FaceRecognition.printPersonInfo(onePerson);
System.out.println("-----------------------------");
Person person2= new Person(2,"jiawen","woman","bbb.",new ArrayList<>(),"Africa","black");
TwoPerson twoPerson2 = new TwoPerson(person2);
FaceRecognition.printPersonInfo(twoPerson2);
}
}
输出:
姓名:huahua
性别:man
肤色:yellow
种族:china
个人行为:[eat, drink, shit, work]
-----------------------------
姓名:jiawen
性别:woman
肤色:black
种族:Africa
个人行为:[eat, drink, shit, play]