赞
踩
对于类来说,一个类应该负责单一项职责。如果存在一个类A负责两个不同的职责,职责1和职责2。当职责1需求发生变化而改变A时,职责2执行错误,这个时候需要将A分解为A1和A2
package single.responsibility;
public class Index {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.run("飞机");
vehicle.run("轮船");
vehicle.run("汽车");
}
}
class Vehicle{
public Vehicle(){
}
public void run(String name){
System.out.println(name + " 运行在路上");
}
}
输出结果
飞机 运行在路上
轮船 运行在路上
汽车 运行在路上
在Vehicle
中,很明显的没有遵守单一职责原则。run方法中适配了所有的情况,不方便于修改
public class Index {
public static void main(String[] args) {
Vehicle aircraft = new Aircraft();
aircraft.run("飞机");
Vehicle car = new Car();
car.run("汽车");
Vehicle ship = new Ship();
ship.run("轮船");
}
}
class Vehicle {
public Vehicle() {
}
public void run(String name) {
}
}
class Car extends Vehicle {
@Override
public void run(String name) {
System.out.println(name + "运行在路上");
}
}
class Ship extends Vehicle {
@Override
public void run(String name) {
System.out.println(name + "运行在海上");
}
}
class Aircraft extends Vehicle {
@Override
public void run(String name) {
System.out.println(name + "运行在天上");
}
}
这种修改方式遵循了单一职责原则,但是缺点是代码量暴增,需要程序员维护的类也对应的变多了。
public class Index {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.runInSea("飞机");
vehicle.runInAir("轮船");
vehicle.runInRoad("汽车");
}
}
class Vehicle {
public Vehicle() {
}
public void runInRoad(String name) {
System.out.println(name + " 运行在路上");
}
public void runInSea(String name) {
System.out.println(name + " 运行在海上");
}
public void runInAir(String name) {
System.out.println(name + " 运行在天上");
}
}
严格来说,这一种修改方式没有完全遵循单一职责原则。但是它将可能依赖在一起的代码隔离开。相对第一种方式而言,第二种需要维护的代码减少。
客户端不应该依赖它不需要的接口,即一个类对另一个依赖应该建立在最小的接口上。
其实通俗来理解就是,不要在一个接口里面放很多的方法,这样会显得这个类很臃肿不堪。接口应该尽量细化,一个接口对应一个功能模块,同时接口里面的方法应该尽可能的少,使接口更加轻便灵活。或许看到接口隔离原则这样的定义很多人会觉得和单一职责原则很像,但是这两个原则还是有着很鲜明的区别。接口隔离原则和单一职责原则的审视角度是不同的,单一职责原则要求类和接口职责单一,注重的是职责,是业务逻辑上的划分,而接口隔离原则要求方法要尽可能的少,是在接口设计上的考虑。例如一个接口的职责包含10个方法,这10个方法都放在一个接口中,并且提供给多个模块访问,各个模块按照规定的权限来访问,并规定了“不使用的方法不能访问”,这样的设计是不符合接口隔离原则的,接口隔离原则要求“尽量使用多个专门的接口”,这里专门的接口就是指提供给每个模块的都应该是单一接口(即每一个模块对应一个接口),而不是建立一个庞大臃肿的接口来容纳所有的客户端访问。
现有A,B,C,D四个类均实现interface1
。其中A只需要方法1,B只需要方法2,C只需要方法3,D只需要方法45。这个时候对于他们而言,interface1
中的除却需要的方法,其他的方法均毫无用处。
解决方案是,将接口interface1
拆分成几个接口。以上述栗子,需要拆分成四个接口,A,B,C,D分别实现对应接口即可
public class Main {
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
}
}
class Email{
public void getInfo(){
System.out.print("收到邮件");
}
}
class Person{
public void receive(Email email){
email.getInfo();
}
}
在这个栗子中,需求是,用户需要接受邮件。上述代码在简单实现的同时,也带了无法拓展的问题。试想一下,如果我们有了新的需求,用户需要接受微信、QQ或者其他的信息呢?我们难道要在Person中定义很多个接受方法吗?
public class Main {
public static void main(String[] args) {
Person person = new Person();
IReceive email = new Email();
person.receive(email);
}
}
interface IReceive{
void getInfo();
}
class Email implements IReceive{
public void getInfo(){
System.out.print("收到邮件");
}
}
class Person{
public void receive(IReceive iReceive){
iReceive.getInfo();
}
}
优化的思路很简单。我们定义一个接受接口IReceive
,如此一来即便我们有了其他的需求,只要实现IReceive
即可。
T1
的对象o1
,都有类型为T2
的对象o2
,使得以T1
定义的所有程序P在所有的对象o1
都替换成o2
时,程序P的行为没有发生变化,那么类型T2
是类型T1
的子类型。换句话说,所有引用基类的地方必须可以透明的使用其子类对象假设现在有一个需求,需要打印学院员工与普通员工的相关信息。
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
CollegeEmployeeMgt collegeEmployeeMgt = new CollegeEmployeeMgt();
collegeEmployeeMgt.printInfo(new EmployeeMgt());
}
}
class Employee {
public Employee(int id) {
this.id = id;
}
int id;
}
class CollegeEmployee {
public CollegeEmployee(int id) {
this.id = id;
}
int id;
}
class EmployeeMgt{
public List<Employee> generateEmployee(){
List<Employee> result = new ArrayList<>();
for (int i = 0 ;i < 10 ; i ++){
result.add(new Employee(i));
}
return result;
}
}
class CollegeEmployeeMgt{
public List<CollegeEmployee> generateEmployee(){
List<CollegeEmployee> result = new ArrayList<>();
for (int i = 0 ;i < 5 ; i ++){
result.add(new CollegeEmployee(i));
}
return result;
}
public void printInfo(EmployeeMgt employeeMgt){
List<Employee> employees = employeeMgt.generateEmployee();
for (Employee employee : employees){
System.out.println("employee" + employee.id);
}
System.out.println("--------------------");
List<CollegeEmployee> collegeEmployees = generateEmployee();
for (CollegeEmployee employee : collegeEmployees){
System.out.println("collegeEmployees" + employee.id);
}
}
}
这段代码的坏味道在哪呢?在printInfo
这个方法中出现了Employee
。这个变量在CollegeEmployeeMgt
类中属于局部变量,而它的作用仅仅只是为了打印。
public class Main {
public static void main(String[] args) {
CollegeEmployeeMgt collegeEmployeeMgt = new CollegeEmployeeMgt();
collegeEmployeeMgt.printInfo(new EmployeeMgt());
}
}
class Employee {
public Employee(int id) {
this.id = id;
}
int id;
}
class CollegeEmployee {
public CollegeEmployee(int id) {
this.id = id;
}
int id;
}
class EmployeeMgt{
public List<Employee> generateEmployee(){
List<Employee> result = new ArrayList<>();
for (int i = 0 ;i < 10 ; i ++){
result.add(new Employee(i));
}
return result;
}
public void printInfo(){
List<Employee> employees = generateEmployee();
for (Employee employee : employees){
System.out.println("employee" + employee.id);
}
}
}
class CollegeEmployeeMgt{
public List<CollegeEmployee> generateEmployee(){
List<CollegeEmployee> result = new ArrayList<>();
for (int i = 0 ;i < 5 ; i ++){
result.add(new CollegeEmployee(i));
}
return result;
}
public void printInfo(EmployeeMgt employeeMgt){
employeeMgt.printInfo();
System.out.println("--------------------");
List<CollegeEmployee> collegeEmployees = generateEmployee();
for (CollegeEmployee employee : collegeEmployees){
System.out.println("collegeEmployees" + employee.id);
}
}
}
优化思路便是新增EmployeeMgt.printInfo
方法用于隐藏相关的打印信息
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。