合成复用原则
原则是尽量使用合成/聚合的方式,而不是使用继承
设计原则核心思想
- 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
- 针对接口编程,而不是针对实现编程。
- 为了交互对象之间的松耦合设计而努力
合成案例
假设我们有一个汽车类(Car),其中包含引擎类(Engine)。下面是使用合成的代码描述:
public class Demo1 {
public static void main(String[] args) {
Car car = new Car("V8");
car.startCar();
car.stopCar();
}
}
// 引擎类
class Engine {
private String type;
public Engine(String type) {
this.type = type;
}
public void start() {
System.out.println("Engine started");
}
public void stop() {
System.out.println("Engine stopped");
}
}
// 汽车类
class Car {
private Engine engine; // 使用合成关系,将引擎组合到汽车中
public Car(String engineType) {
engine = new Engine(engineType); // 在构造函数中创建引擎对象
}
public void startCar() {
engine.start(); // 调用引擎对象的启动方法
}
public void stopCar() {
engine.stop(); // 调用引擎对象的停止方法
}
}
在上面的代码中,我在汽车类中添加了一个静态的main方法。在main方法中,我创建了一辆汽车对象,并指定了引擎类型为"V8"。然后,我调用了汽车对象的启动方法和停止方法,以展示汽车的功能。
您可以运行这个Java程序,看到在控制台输出的结果,显示汽车的启动和停止过程。
这个示例展示了如何在汽车类中使用合成关系,将引擎对象组合到汽车中,并通过main方法来演示汽车的使用
聚合案例
public class Demo2 {
public static void main(String[] args) {
School school = new School(); // 创建一个学校对象
// 创建学生对象
Student student1 = new Student("Alice");
Student student2 = new Student("Bob");
Student student3 = new Student("Charlie");
// 将学生对象添加到学校中
school.addStudent(student1);
school.addStudent(student2);
school.addStudent(student3);
// 显示学校中的学生
school.displayStudents();
}
}
//学生类
class Student {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
//学校类
class School {
private List<Student> students; // 使用聚合关系,将学生聚合到学校中
public School() {
students = new ArrayList<>(); // 在构造函数中创建学生列表对象
}
public void addStudent(Student student) {
students.add(student); // 将学生对象添加到学生列表中
}
public void displayStudents() {
for (Student student : students) {
System.out.println(student.getName());
}
}
}
在上面的代码中,学校类(School)使用聚合关系,将学生对象(Student)聚合到学校中。学校类通过添加学生对象到学生列表中,并提供了显示学生的方法。
学生类(Student)是一个简单的类,表示学生。它有一个姓名属性和获取姓名的方法。
通过使用聚合关系,我们可以实现学校类的代码复用和灵活性。学校类通过聚合学生对象来管理学生。这种设计方式避免了继承关系的局限性,使系统更加灵活和可维护。
在main方法中,我创建了一个学校对象,并创建了几个学生对象。然后,我将学生对象添加到学校中,并调用学校对象的显示学生方法,以展示学校中的学生信息。
这个示例展示了如何在学校类中使用聚合关系,将学生对象聚合到学校中,并通过main方法来演示学校的学生管理。
继承案例
class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public void makeSound() {
System.out.println("The animal makes a sound.");
}
}
class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println("The dog barks.");
}
}
class Cat extends Animal {
public Cat(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println("The cat meows.");
}
}
public class Main {
public static void main(String[] args) {
Animal animal1 = new Dog("Buddy");
Animal animal2 = new Cat("Whiskers");
animal1.makeSound(); // Output: The dog barks.
animal2.makeSound(); // Output: The cat meows.
}
}
在上面的代码中,Animal 类是一个基类,它有一个私有的 name 属性和一个 makeSound 方法。Dog 类和 Cat 类都继承自 Animal 类,并重写了 makeSound 方法,以实现各自的特定声音。
在 main 方法中,我们创建了一个 Dog 对象和一个 Cat 对象,并将它们赋值给 Animal 类型的变量。然后,我们调用这些对象的 makeSound 方法,分别输出狗的吠声和猫的喵声。
这个示例展示了如何使用继承来创建一个动物类的继承体系。通过继承,我们可以在派生类中重用基类的属性和方法,并根据需要进行定制化。继承提供了代码的复用和扩展性,但也需要注意继承关系的合理使用,避免过度继承和耦合。
优缺点
与继承关系相比,合成复用原则具有以下优点:
- 更加灵活:通过合成或聚合关系,可以在运行时动态地改变对象的行为,而不需要修改代码。
- 降低耦合性:合成或聚合关系可以减少类之间的依赖关系,降低耦合性,使系统更加灵活和可维护。
- 更好的代码复用:通过合成或聚合关系,可以将现有的类组合在一起,创建新的类来实现代码的复用,避免了继承关系的局限性。