外观
组合、继承、代理的区别
来源:语雀原文 | 整理日期:2026-09-22
在Java编程中,组合(Composition)、继承(Inheritance)和代理(Delegation)是实现代码复用和对象关系的重要方式。它们各有特点和适用场景,以下是它们的区别和使用方式:
1. 组合(Composition)
组合是指一个类包含另一个类的实例作为其成员变量,从而通过这个成员变量来实现功能。换句话说,组合是一种“has-a”(有一个)关系。
优点:
- 组合提供了更灵活的设计,因为可以在运行时决定对象的组合。
- 它允许类之间的耦合度较低,因为类之间没有强制的继承关系,只是基于接口或实现类进行协作。
示例代码:
java
public class Composition {
public static void main(String[] args) {
Car car = new Car();
car.startCar();
}
}
class Engine {
void start() {
System.out.println("Engine start");
}
}
class Car {
private Engine engine = new Engine();
void startCar() {
engine.start();
System.out.println("Car started");
}
}2. 继承(Inheritance)
继承是面向对象编程中的一种机制,一个类可以继承另一个类的属性和方法,从而实现代码复用和扩展。继承是一种“is-a”(是一种)关系。
优点:
- 让子类复用父类的代码,提高代码的复用性。
- 子类可以通过继承父类来扩展和扩充功能。
缺点:
- 继承使得子类和父类之间耦合度较高,当父类发生变化时,子类可能也需要相应地改变。
- Java 不支持多重继承。
示例代码:
java
public class Inheritance {
public static void main(String[] args) {
Dog dog = new Dog();
dog.makeSound(); // Outputs "Woof"
}
}
class Animal {
void makeSound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Woof");
}
}3. 代理(Delegation)
代理模式是一种设计模式,它允许一个对象为另外一个对象提供代理访问。代理通常用来控制对对象的访问,可以用于延迟初始化、访问控制等场景。代理是一种“delegate-to”(委派到)关系。
优点:
- 通过代理可以在不改变原有类的情况下扩展功能。
- 可以对对象的访问进行控制,如添加日志、权限控制等。
我们可以通过代理模式实现对某个对象的访问控制,例如验证权限。
示例代码:
java
// Subject接口
public interface Subject {
void request();
}
// RealSubject类
public class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
// Proxy类
public class Proxy implements Subject {
private RealSubject realSubject;
private String userRole;
public Proxy(String userRole) {
this.userRole = userRole;
}
public void request() {
// 进行权限检查
if (this.userRole.equals("Admin")) {
if (realSubject == null) {
realSubject = new RealSubject();
}
realSubject.request();
} else {
System.out.println("Proxy: Access denied. Only Admin can access.");
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Proxy proxy = new Proxy("User");
proxy.request(); // 输出:Proxy: Access denied. Only Admin can access.
Proxy adminProxy = new Proxy("Admin");
adminProxy.request(); // 输出:RealSubject: Handling request.
}
}总结
- 组合强调的是“has-a”(有一个)关系,使用成员变量来表示两个类之间的关系。
- 继承强调的是“is-a”(是一种)关系,使用继承来实现代码复用和多态性。
- 代理则是通过一个代理对象来间接访问真正的目标对象,常用于控制访问、延迟初始化等场景。
根据具体情况选择合适的方式,可以提高代码的可维护性和复用性。