面向对象(精髓)变继承关系为组和关系(State模式)

文章讨论了面向对象编程中继承关系的局限性,提倡使用组合关系来代替,通过接口定义角色行为,以实现更灵活、可维护的设计。作者比较了继承与组合的关系,并提供了使用组合关系优化设计的示例。
摘要由CSDN通过智能技术生成

在这里插入图片描述
在面向对象编程中,继承关系是一种重要的关系类型,它允许一个类(子类)继承另一个类(父类)的属性和方法。然而,随着软件系统的复杂性不断增加,传统的继承关系可能会导致代码的臃肿和耦合度的增加。为了解决这一问题,我们可以使用组合关系来取代继承关系,将对象的功能模块化,并通过接口定义角色行为,从而实现更加灵活和可维护的设计。本文将探讨面向对象编程中继承关系与组合关系的区别,以及如何合理运用组合关系来优化设计,提高代码的质量和可维护性。

  //面向对象(精髓)变继承关系为组和关系 
  public Employee(String name, int salary) {
    this.name = name;
    this.salary = salary;
  }
  public void doWork() {
// 更具需求实现功能
  }
  ....省略...
public class Manager extends Employee {
  private final List<Employee> reporters;//下属
  public void doWork() {
// 项目领导工作给下属分配需求工作
  }
  
 	Employee employee1 = new Employee("John", 10000);
    Employee employee2 = new Employee("Mary", 20000);
    Employee employee3 = new Employee("John", 10000);
 
   

//employee2 升级成领导Manager 工资增长5w 并管理其他下属
//打印员工晋升为领导前后的工作内容。

思考如果莫员工(employee2 )升级成领导Manager 怎么优化设计

在这里插入图片描述

不推荐写法(继承关系)

public class Employee {
    private String name;
    private int salary;
     
    // 构造函数
    public Employee(String name, int salary) {
        this.name = name;
        this.salary = salary;
    }
    // 工作方法
    public void doWork() {
        // 员工的工作逻辑
    }
}

public class Manager extends Employee {
 	// 管理员属性在这里
    private List<Employee> reporters;
    // 管理员的工作方法
    @Override
    public void doWork() {
        // 项目领导的工作逻辑
    }
     // 获取下属
    public List<Employee> getReporters() {
        return reporters;
    }
}

在不推荐的继承关系写法中,Manager 类继承自 Employee 类。虽然从某种程度上看,Manager 是一种特殊的 Employee,但这种继承关系存在一些缺点:

  1. 僵化的层次结构:使用继承关系会将 ManagerEmployee 类紧密耦合在一起,形成了僵化的层次结构。如果未来需要引入其他类型的员工,如实习生或兼职员工,就需要修改现有的继承结构,导致系统的扩展性变差。

  2. 不符合"IS-A"关系:继承关系应该满足 “IS-A” 关系,即子类对象可以替代父类对象使用。但 ManagerEmployee 之间的关系不是严格的 “IS-A” 关系。Manager 是一种特殊的员工,但并不是所有员工都是经理。

  3. 职责混淆Manager 类继承了 Employee 类中的一些属性和方法,如 namesalary,但与之相应的 doWork() 方法的实现完全不同。这导致了职责的混淆,使得代码难以理解和维护。

  4. 困难的扩展:在继承关系中,子类继承了父类的全部行为,包括一些可能并不适用于子类的行为。这样就限制了子类的灵活性和可扩展性,使得后续对于子类的修改和扩展变得困难。

综上所述,尽管继承关系在某些情况下很有用,但在这个场景下使用继承关系存在着上述的缺点,因此不推荐使用继承关系来表示 ManagerEmployee 之间的关系。

推荐写法(组合关系)

在这里插入图片描述

// 角色接口
interface Role {
    void doWork();
}

// 工程师角色
class Engineer implements Role {
    @Override
    public void doWork() {
        // 工程师的工作逻辑
    }
}

// 经理角色
class Manager implements Role {
    private List<Employee> reporters;

    // 构造函数
    public Manager(List<Employee> reporters) {
        this.reporters = reporters;
    }

    @Override
    public void doWork() {
        // 项目领导的工作逻辑
    }

    // 获取下属
    public List<Employee> getReporters() {
        return reporters;
    }
}

public class Employee {
    private String name;
    private int salary;
    private Role role; // 当前角色职位

    // 构造函数
    public Employee(String name, int salary, Role role) {
        this.name = name;
        this.salary = salary;
        this.role = role;
    }

    // 获取当前角色
    public Role getRole() {
        return role;
    }
	// 执行工作
    public void doWork() {
        role.doWork();
    }

}
class Tester{
    public static void main(String[] args) {
        Employee employee1 = new Employee("John", 10000);
        Employee employee2 = new Employee("Mary", 20000);
        Employee employee3 = new Employee("John", 10000);

        employee2.doWork();//output 更具需求实现功能...
        employee2.setRole(new Manager(Arrays.asList(employee1,employee3)));
        employee2.doWork();//output 项目领导工作给下属分配需求工作...
    }
}

推荐的组合关系写法采用了 State 模式,相比不推荐的继承关系写法,具有以下优点:

  1. 灵活性和可扩展性:组合关系将角色和功能分离开来,使得系统更加灵活和可扩展。在组合关系中,Employee 类可以根据需要动态地切换不同的角色,而不需要修改现有的代码结构。这样一来,系统可以更加容易地适应需求的变化,保持良好的扩展性。

  2. 降低耦合度:组合关系降低了对象之间的耦合度,使得系统更加灵活和可维护。在组合关系中,Employee 类与具体的角色实现类之间仅通过接口进行交互,彼此之间相互独立。这样一来,系统的各个部分之间的依赖关系更加清晰,代码的耦合度更低,使得系统更加易于理解和维护。

  3. 符合"HAS-A"关系:组合关系符合 “HAS-A” 关系,即一个对象包含另一个对象作为其组成部分。在组合关系中,Employee 类包含了一个 Role 类的引用,表示员工拥有某种角色。这种关系更加贴近现实世界的对象之间的关系,使得系统的设计更加自然和直观。

  4. 清晰的责任分配:组合关系将不同的职责分配到了不同的类中,使得每个类都专注于自己的核心职责。在组合关系中,Employee 类负责管理员工的基本信息,而 Role 接口负责定义员工的角色和行为。这样一来,每个类的职责更加清晰明确,代码更加易于理解和维护。

综上所述,推荐的组合关系写法采用了 State 模式,相比不推荐的继承关系写法,具有更高的灵活性、可扩展性、低耦合度和清晰的责任分配。因此,在设计类和对象时,应该优先考虑使用组合关系,以提高代码的质量和可维护性。

总结

在面向对象设计中,推荐使用组合关系而不是继承关系。组合关系将对象的功能和角色分离,使得对象更加灵活和可复用。通过组合关系,可以将不同的角色和功能组合起来,从而实现更加复杂的行为。同时,组合关系也降低了对象之间的耦合度,使得系统更加易于维护和扩展。因此,在设计类和对象时,应该优先考虑使用组合关系,从而提高代码的质量和可维护性。


扩展阅读

在这里插入图片描述

面向对象主题链接
类与对象链接
接口与抽象类链接
不可变性链接
变继承为组合(精髓一)状态模式链接
变继承为组合(精髓二)装饰器模式链接

完整代码示例

// 定义状态接口
interface Role {
    void doWork();
}

// 具体状态:普通员工
class Engineer implements Role {
    @Override
    public void doWork() {
        System.out.println("更具需求实现功能...");
    }
}

// 具体状态:经理
class Manager implements Role {
    private  List<Employee> reporters;

    public Manager(List<Employee> reporters) {
        this.reporters = reporters;
    }

    @Override
    public void doWork() {
        System.out.println("项目领导工作给下属分配需求工作...");
    }
}
@Data
@AllArgsConstructor
// 上下文类:员工
 class Employee {
    private String name;
    private int salary;
    private Role role; // 当前角色状态

    public Employee(String name, int salary) {
        this.name = name;
        this.salary = salary;
        this.role = new Engineer(); // 默认状态为普通员工
    }

    // 设置角色状态
    public void setRole(Role role) {
        this.role = role;
    }

    // 执行工作
    public void doWork() {
        role.doWork();
    }

}

class Tester{
    public static void main(String[] args) {
        Employee employee1 = new Employee("John", 10000);
        Employee employee2 = new Employee("Mary", 20000);
        Employee employee3 = new Employee("John", 10000);

        employee2.doWork();//output 更具需求实现功能...

        employee2.setRole(new Manager(Arrays.asList(employee1,employee3)));

        employee2.doWork();//output 项目领导工作给下属分配需求工作...
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值