淘先锋技术网

首页 1 2 3 4 5 6 7

合成复用原则

原则是尽量使用合成/聚合的方式,而不是使用继承

设计原则核心思想

  1. 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
  2. 针对接口编程,而不是针对实现编程。
  3. 为了交互对象之间的松耦合设计而努力

合成案例

假设我们有一个汽车类(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 方法,分别输出狗的吠声和猫的喵声。

这个示例展示了如何使用继承来创建一个动物类的继承体系。通过继承,我们可以在派生类中重用基类的属性和方法,并根据需要进行定制化。继承提供了代码的复用和扩展性,但也需要注意继承关系的合理使用,避免过度继承和耦合。

优缺点

与继承关系相比,合成复用原则具有以下优点:

  • 更加灵活:通过合成或聚合关系,可以在运行时动态地改变对象的行为,而不需要修改代码。
  • 降低耦合性:合成或聚合关系可以减少类之间的依赖关系,降低耦合性,使系统更加灵活和可维护。
  • 更好的代码复用:通过合成或聚合关系,可以将现有的类组合在一起,创建新的类来实现代码的复用,避免了继承关系的局限性。