1. 多态概念解析
多态是面向对象编程的三大特性之一(封装、继承、多态),它允许不同类的对象对同一消息做出不同的响应。简单来说,就是"一个接口,多种实现"。在实际开发中,我们经常会遇到这样的场景:需要处理一组对象,这些对象属于不同的类,但它们有共同的父类或接口,我们希望用统一的方式来操作它们,而每个对象又能表现出自己特有的行为。
举个生活中的例子:假设我们有一个"动物"父类,以及"猫"、"狗"、"鸟"等子类。当调用"发出声音"这个方法时,猫会"喵喵"叫,狗会"汪汪"叫,鸟会"叽叽喳喳"叫。这就是多态的典型表现——同样的方法调用,在不同对象上产生了不同的行为。
注意:多态的实现依赖于继承和方法重写,没有继承关系就无法实现真正的多态。
2. 多态的实现方式
2.1 编译时多态(静态多态)
编译时多态主要通过方法重载(Overload)实现。在同一个类中,允许存在多个同名方法,只要它们的参数列表不同(参数类型、个数或顺序不同)。编译器在编译时就能确定调用哪个方法。
java复制public class Calculator {
// 方法重载示例
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public String add(String a, String b) {
return a + b;
}
}
2.2 运行时多态(动态多态)
运行时多态主要通过方法重写(Override)实现。子类可以重写父类的方法,当通过父类引用调用这个方法时,实际执行的是子类重写后的方法。具体调用哪个方法是在程序运行时根据对象的实际类型决定的。
java复制class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("喵喵");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("汪汪");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal(); // Animal对象
Animal myCat = new Cat(); // Cat对象
Animal myDog = new Dog(); // Dog对象
myAnimal.makeSound(); // 输出: 动物发出声音
myCat.makeSound(); // 输出: 喵喵
myDog.makeSound(); // 输出: 汪汪
}
}
3. 多态的核心机制
3.1 向上转型(Upcasting)
向上转型是指将子类对象赋值给父类引用变量,这是多态实现的基础。向上转型是自动进行的,不需要显式转换。
java复制Animal animal = new Cat(); // 向上转型
3.2 动态绑定(Dynamic Binding)
动态绑定是指方法调用与方法实现的关联是在运行时进行的,而不是在编译时。这是实现运行时多态的关键机制。
3.3 方法表(Method Table)
JVM为每个类维护一个方法表,其中存储了该类所有方法的实际入口地址。当调用一个方法时,JVM会根据对象的实际类型查找对应的方法表,然后找到具体的方法实现。
4. 多态的高级应用
4.1 接口多态
接口定义了一组方法规范,任何实现该接口的类都必须实现这些方法。通过接口引用可以调用不同实现类的方法,实现多态。
java复制interface Shape {
double getArea();
}
class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double getArea() {
return width * height;
}
}
public class Main {
public static void printArea(Shape shape) {
System.out.println("面积: " + shape.getArea());
}
public static void main(String[] args) {
Shape circle = new Circle(5);
Shape rectangle = new Rectangle(4, 6);
printArea(circle); // 输出圆的面积
printArea(rectangle); // 输出矩形的面积
}
}
4.2 策略模式中的多态应用
策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。
java复制interface PaymentStrategy {
void pay(int amount);
}
class CreditCardPayment implements PaymentStrategy {
private String name;
private String cardNumber;
public CreditCardPayment(String name, String cardNumber) {
this.name = name;
this.cardNumber = cardNumber;
}
@Override
public void pay(int amount) {
System.out.println(amount + "元通过信用卡支付");
}
}
class AlipayPayment implements PaymentStrategy {
private String email;
public AlipayPayment(String email) {
this.email = email;
}
@Override
public void pay(int amount) {
System.out.println(amount + "元通过支付宝支付");
}
}
class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void checkout(int amount) {
paymentStrategy.pay(amount);
}
}
public class Main {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 使用信用卡支付
cart.setPaymentStrategy(new CreditCardPayment("张三", "123456789"));
cart.checkout(100);
// 使用支付宝支付
cart.setPaymentStrategy(new AlipayPayment("zhangsan@example.com"));
cart.checkout(200);
}
}
5. 多态的使用注意事项
5.1 方法覆盖的规则
- 子类方法的访问权限不能比父类方法更严格
- 子类方法的返回类型可以是父类方法返回类型的子类(协变返回类型)
- 子类方法不能抛出比父类方法更多的异常
- 被覆盖的方法不能是private、final或static的
5.2 多态与字段访问
多态只适用于方法调用,不适用于字段访问。字段访问是由引用类型决定的,而不是实际对象类型。
java复制class SuperClass {
public String field = "SuperClass Field";
public void printField() {
System.out.println(field);
}
}
class SubClass extends SuperClass {
public String field = "SubClass Field";
@Override
public void printField() {
System.out.println(field);
}
}
public class Main {
public static void main(String[] args) {
SuperClass instance = new SubClass();
System.out.println(instance.field); // 输出: SuperClass Field
instance.printField(); // 输出: SubClass Field
}
}
5.3 构造器与多态
在构造器中调用多态方法可能会导致问题,因为此时子类的构造可能还未完成。
java复制class Glyph {
void draw() {
System.out.println("Glyph.draw()");
}
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}
class RoundGlyph extends Glyph {
private int radius = 1;
RoundGlyph(int r) {
radius = r;
System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);
}
@Override
void draw() {
System.out.println("RoundGlyph.draw(), radius = " + radius);
}
}
public class Main {
public static void main(String[] args) {
new RoundGlyph(5);
}
}
输出结果:
code复制Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
6. 多态的性能考量
6.1 方法调用的开销
普通方法调用(非虚方法)的性能开销较小,而虚方法调用(可能涉及多态)的性能开销相对较大,因为需要在运行时确定具体调用的方法。
6.2 内联优化
JVM会对频繁调用的方法进行内联优化,但对于虚方法,只有在能够确定具体实现的情况下才能进行内联。使用final修饰的方法或类可以帮助JVM做出更好的优化决策。
6.3 多态与缓存
在设计缓存系统时,需要考虑多态带来的影响。例如,当缓存的对象可能有多种子类实现时,序列化和反序列化过程需要正确处理类型信息。
7. 多态在实际项目中的应用技巧
7.1 工厂模式中的多态
工厂模式利用多态来创建对象,客户端代码只需要知道抽象类型,不需要关心具体的实现类。
java复制interface Logger {
void log(String message);
}
class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("记录到文件: " + message);
}
}
class DatabaseLogger implements Logger {
@Override
public void log(String message) {
System.out.println("记录到数据库: " + message);
}
}
class LoggerFactory {
public static Logger getLogger(String type) {
if ("file".equalsIgnoreCase(type)) {
return new FileLogger();
} else if ("database".equalsIgnoreCase(type)) {
return new DatabaseLogger();
}
throw new IllegalArgumentException("不支持的日志类型");
}
}
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger("file");
logger.log("这是一个测试消息");
}
}
7.2 回调机制中的多态
回调是一种常见的多态应用,通过定义回调接口,允许调用者提供具体的实现。
java复制interface ClickListener {
void onClick();
}
class Button {
private ClickListener listener;
public void setClickListener(ClickListener listener) {
this.listener = listener;
}
public void click() {
if (listener != null) {
listener.onClick();
}
}
}
public class Main {
public static void main(String[] args) {
Button button = new Button();
// 设置匿名内部类作为回调
button.setClickListener(new ClickListener() {
@Override
public void onClick() {
System.out.println("按钮被点击了");
}
});
button.click();
}
}
7.3 集合框架中的多态
Java集合框架广泛使用了多态。例如,List接口有多种实现类(ArrayList、LinkedList等),我们可以根据需要选择合适的实现,而使用代码不需要改变。
java复制import java.util.*;
public class Main {
public static void printList(List<String> list) {
for (String item : list) {
System.out.println(item);
}
}
public static void main(String[] args) {
List<String> arrayList = new ArrayList<>();
arrayList.add("ArrayList 元素1");
arrayList.add("ArrayList 元素2");
List<String> linkedList = new LinkedList<>();
linkedList.add("LinkedList 元素1");
linkedList.add("LinkedList 元素2");
printList(arrayList);
printList(linkedList);
}
}
8. 多态的设计原则
8.1 里氏替换原则(LSP)
里氏替换原则指出:子类必须能够替换它们的基类而不影响程序的正确性。这意味着子类不应该改变父类方法的行为,只能扩展它。
8.2 依赖倒置原则(DIP)
依赖倒置原则强调:高层模块不应该依赖低层模块,二者都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象。多态是实现这一原则的关键技术。
8.3 开闭原则(OCP)
开闭原则要求软件实体应该对扩展开放,对修改关闭。通过多态,我们可以在不修改现有代码的情况下,通过添加新的子类来扩展系统功能。
9. 多态在测试中的应用
9.1 使用Mock对象
在单元测试中,我们可以利用多态创建Mock对象来替代真实的依赖对象,从而隔离测试目标。
java复制interface UserService {
User getUserById(int id);
}
class RealUserService implements UserService {
@Override
public User getUserById(int id) {
// 实际从数据库获取用户
return db.queryUserById(id);
}
}
class MockUserService implements UserService {
@Override
public User getUserById(int id) {
// 返回测试用的模拟用户
return new User(id, "测试用户");
}
}
public class UserControllerTest {
@Test
public void testGetUser() {
UserController controller = new UserController();
controller.setUserService(new MockUserService()); // 注入Mock服务
User user = controller.getUser(1);
assertEquals("测试用户", user.getName());
}
}
9.2 测试抽象类
对于抽象类,我们可以创建一个用于测试的具体子类来测试抽象类的行为。
java复制abstract class AbstractProcessor {
public abstract void process();
public void execute() {
// 一些预处理
process();
// 一些后处理
}
}
class TestProcessor extends AbstractProcessor {
private boolean processed = false;
@Override
public void process() {
processed = true;
}
public boolean isProcessed() {
return processed;
}
}
public class AbstractProcessorTest {
@Test
public void testExecute() {
TestProcessor processor = new TestProcessor();
processor.execute();
assertTrue(processor.isProcessed());
}
}
10. 多态与设计模式
多态是许多设计模式的基础,下面列举几个典型模式中的多态应用:
10.1 模板方法模式
模板方法模式定义了一个算法的骨架,将某些步骤延迟到子类中实现。父类的模板方法调用这些抽象操作,具体实现由子类提供。
java复制abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
// 模板方法
public final void play() {
initialize();
startPlay();
endPlay();
}
}
class Cricket extends Game {
@Override
void initialize() {
System.out.println("板球游戏初始化");
}
@Override
void startPlay() {
System.out.println("板球游戏开始");
}
@Override
void endPlay() {
System.out.println("板球游戏结束");
}
}
class Football extends Game {
@Override
void initialize() {
System.out.println("足球游戏初始化");
}
@Override
void startPlay() {
System.out.println("足球游戏开始");
}
@Override
void endPlay() {
System.out.println("足球游戏结束");
}
}
public class Main {
public static void main(String[] args) {
Game game = new Cricket();
game.play();
game = new Football();
game.play();
}
}
10.2 装饰器模式
装饰器模式动态地给对象添加额外的职责,是继承的一个替代方案。它通过创建一个包装对象来扩展功能,同时保持接口的一致性。
java复制interface Coffee {
double getCost();
String getDescription();
}
class SimpleCoffee implements Coffee {
@Override
public double getCost() {
return 1.0;
}
@Override
public String getDescription() {
return "普通咖啡";
}
}
abstract class CoffeeDecorator implements Coffee {
protected final Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
@Override
public double getCost() {
return decoratedCoffee.getCost();
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription();
}
}
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double getCost() {
return super.getCost() + 0.5;
}
@Override
public String getDescription() {
return super.getDescription() + ", 加牛奶";
}
}
class WhipDecorator extends CoffeeDecorator {
public WhipDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double getCost() {
return super.getCost() + 0.7;
}
@Override
public String getDescription() {
return super.getDescription() + ", 加奶油";
}
}
public class Main {
public static void main(String[] args) {
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.getDescription() + ": $" + coffee.getCost());
coffee = new MilkDecorator(coffee);
System.out.println(coffee.getDescription() + ": $" + coffee.getCost());
coffee = new WhipDecorator(coffee);
System.out.println(coffee.getDescription() + ": $" + coffee.getCost());
}
}
10.3 观察者模式
观察者模式定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
java复制import java.util.ArrayList;
import java.util.List;
interface Observer {
void update(String message);
}
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
class NewsAgency implements Subject {
private List<Observer> observers = new ArrayList<>();
private String news;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(news);
}
}
public void setNews(String news) {
this.news = news;
notifyObservers();
}
}
class NewsChannel implements Observer {
private String news;
@Override
public void update(String news) {
this.news = news;
display();
}
public void display() {
System.out.println("收到新闻更新: " + news);
}
}
public class Main {
public static void main(String[] args) {
NewsAgency agency = new NewsAgency();
NewsChannel channel1 = new NewsChannel();
NewsChannel channel2 = new NewsChannel();
agency.registerObserver(channel1);
agency.registerObserver(channel2);
agency.setNews("重要新闻: 多态是面向对象的核心特性之一");
}
}
11. 多态在框架开发中的应用
11.1 Spring框架中的依赖注入
Spring框架利用多态实现依赖注入,通过接口定义依赖关系,运行时注入具体的实现。
java复制public interface MessageService {
String getMessage();
}
public class EmailService implements MessageService {
@Override
public String getMessage() {
return "Email Message";
}
}
public class SMSService implements MessageService {
@Override
public String getMessage() {
return "SMS Message";
}
}
@Service
public class NotificationService {
private final MessageService messageService;
@Autowired
public NotificationService(MessageService messageService) {
this.messageService = messageService;
}
public void sendNotification() {
System.out.println(messageService.getMessage());
}
}
// 配置类
@Configuration
public class AppConfig {
@Bean
public MessageService messageService() {
// 可以轻松切换实现
return new EmailService();
// return new SMSService();
}
}
11.2 Java集合框架中的迭代器
集合框架通过Iterator接口提供了统一的遍历集合元素的方式,不同的集合类提供自己的迭代器实现。
java复制List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
Set<String> set = new HashSet<>();
set.add("X");
set.add("Y");
set.add("Z");
// 使用相同的接口遍历不同的集合
printElements(list.iterator());
printElements(set.iterator());
public static void printElements(Iterator<String> iterator) {
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
11.3 JDBC中的驱动管理
JDBC通过DriverManager和Connection接口屏蔽了不同数据库的具体实现细节。
java复制// 使用相同的接口操作不同的数据库
Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
// 处理结果集
while (rs.next()) {
System.out.println(rs.getString("username"));
}
12. 多态与泛型的结合
泛型可以与多态结合使用,提供更灵活的类型安全编程方式。
12.1 泛型方法中的多态
java复制public class Util {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
}
public class Main {
public static void main(String[] args) {
Integer[] intArray = {1, 2, 3};
String[] stringArray = {"Hello", "World"};
Util.printArray(intArray);
Util.printArray(stringArray);
}
}
12.2 泛型类与多态
java复制class Box<T> {
private T content;
public void setContent(T content) {
this.content = content;
}
public T getContent() {
return content;
}
}
public class Main {
public static void main(String[] args) {
Box<Integer> intBox = new Box<>();
intBox.setContent(123);
Box<String> strBox = new Box<>();
strBox.setContent("Hello Generics");
System.out.println(intBox.getContent());
System.out.println(strBox.getContent());
}
}
12.3 有界类型参数
java复制interface Comparable<T> {
int compareTo(T other);
}
class SortedList<T extends Comparable<T>> {
private List<T> list = new ArrayList<>();
public void add(T element) {
// 实现排序插入逻辑
}
public T get(int index) {
return list.get(index);
}
}
class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return this.age - other.age;
}
@Override
public String toString() {
return name + "(" + age + ")";
}
}
public class Main {
public static void main(String[] args) {
SortedList<Person> people = new SortedList<>();
people.add(new Person("Alice", 25));
people.add(new Person("Bob", 30));
people.add(new Person("Charlie", 20));
System.out.println(people.get(0)); // Charlie(20)
System.out.println(people.get(1)); // Alice(25)
System.out.println(people.get(2)); // Bob(30)
}
}
13. 多态与Lambda表达式
Java 8引入的Lambda表达式和方法引用进一步扩展了多态的应用场景。
13.1 使用Lambda实现函数式接口
java复制@FunctionalInterface
interface Greeting {
void sayHello(String name);
}
public class Main {
public static void main(String[] args) {
// 使用Lambda表达式实现接口
Greeting englishGreeting = name -> System.out.println("Hello, " + name);
Greeting chineseGreeting = name -> System.out.println("你好, " + name);
englishGreeting.sayHello("Alice");
chineseGreeting.sayHello("张三");
}
}
13.2 集合操作中的Lambda
java复制import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// 使用Lambda表达式进行集合操作
names.forEach(name -> System.out.println(name));
// 使用方法引用
names.forEach(System.out::println);
// 使用Lambda表达式过滤
names.stream()
.filter(name -> name.startsWith("A"))
.forEach(System.out::println);
}
}
13.3 自定义函数式接口
java复制@FunctionalInterface
interface StringProcessor {
String process(String input);
default StringProcessor andThen(StringProcessor after) {
return input -> after.process(this.process(input));
}
}
public class Main {
public static void main(String[] args) {
StringProcessor toUpperCase = String::toUpperCase;
StringProcessor addExclamation = s -> s + "!";
StringProcessor addQuestion = s -> s + "?";
StringProcessor processor = toUpperCase
.andThen(addExclamation)
.andThen(addQuestion);
System.out.println(processor.process("hello")); // 输出: HELLO!?
}
}
14. 多态的最佳实践
14.1 何时使用多态
- 当需要处理一组相关对象,且这些对象有共同的行为但具体实现不同时
- 当需要在不修改现有代码的情况下扩展系统功能时
- 当需要解耦接口和实现时
- 当需要实现回调机制或事件处理时
14.2 多态的设计建议
- 优先使用接口定义行为,而不是抽象类
- 遵循"针对接口编程,而不是针对实现编程"的原则
- 保持方法的重写行为一致,不要改变父类方法的预期行为
- 合理使用设计模式,如策略模式、工厂模式等
- 考虑使用组合而不是继承来实现多态行为
14.3 多态的常见误用
- 过度使用继承导致类层次过深
- 不恰当地重写方法,改变了父类方法的预期行为
- 在构造器中调用可重写方法
- 忽视多态带来的性能影响(在性能关键代码中)
- 使用多态实现本应使用条件语句的逻辑
15. 多态在不同语言中的实现
虽然多态是面向对象编程的核心概念,但在不同语言中的实现方式有所不同。
15.1 Java中的多态
Java通过继承和方法重写实现运行时多态,通过方法重载实现编译时多态。Java 8引入的默认方法和静态方法扩展了接口的多态能力。
15.2 C++中的多态
C++通过虚函数(virtual function)实现运行时多态,需要使用virtual关键字显式声明。C++还支持运算符重载和模板元编程等更丰富的多态形式。
15.3 Python中的多态
Python作为动态类型语言,多态更加灵活。任何实现了特定方法的对象都可以被当作特定类型使用(鸭子类型)。Python还支持运算符重载和抽象基类。
15.4 JavaScript中的多态
JavaScript通过原型继承实现多态。由于JavaScript是动态类型语言,多态的实现更加灵活,任何对象只要实现了特定方法就可以被当作特定类型使用。
16. 多态的性能优化
16.1 减少虚方法调用
在性能关键代码中,可以考虑减少虚方法调用,或者使用final修饰不需要重写的方法。
16.2 使用内联缓存
一些JVM实现使用内联缓存(Inline Cache)来优化虚方法调用,缓存最近使用的方法实现。
16.3 避免多态在热点代码中的过度使用
在性能敏感的热点代码中,可以考虑使用条件语句替代多态,或者使用策略枚举等模式。
17. 多态与并发编程
17.1 多态与线程安全
当多态方法被多个线程同时调用时,需要确保方法的线程安全性。可以考虑:
- 使方法无状态(不访问共享数据)
- 使用同步机制保护共享数据
- 使用不可变对象
17.2 并发集合中的多态
Java并发集合框架如ConcurrentHashMap通过多态提供线程安全的集合操作。
java复制ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("one", 1);
map.put("two", 2);
// 线程安全的操作
map.computeIfAbsent("three", k -> 3);
17.3 异步回调中的多态
在异步编程中,回调接口通常通过多态实现,允许调用者提供不同的回调实现。
java复制interface Callback {
void onComplete(String result);
void onError(Exception e);
}
class AsyncTask {
public void execute(Callback callback) {
new Thread(() -> {
try {
// 模拟耗时操作
Thread.sleep(1000);
callback.onComplete("操作完成");
} catch (InterruptedException e) {
callback.onError(e);
}
}).start();
}
}
public class Main {
public static void main(String[] args) {
AsyncTask task = new AsyncTask();
task.execute(new Callback() {
@Override
public void onComplete(String result) {
System.out.println(result);
}
@Override
public void onError(Exception e) {
e.printStackTrace();
}
});
System.out.println("异步任务已启动");
}
}
18. 多态与设计模式进阶
18.1 访问者模式
访问者模式将算法与对象结构分离,通过在访问者接口中定义访问不同类型元素的方法,实现对复杂对象结构的操作。
java复制interface ComputerPart {
void accept(ComputerPartVisitor visitor);
}
class Keyboard implements ComputerPart {
@Override
public void accept(ComputerPartVisitor visitor) {
visitor.visit(this);
}
}
class Monitor implements ComputerPart {
@Override
public void accept(ComputerPartVisitor visitor) {
visitor.visit(this);
}
}
interface ComputerPartVisitor {
void visit(Keyboard keyboard);
void visit(Monitor monitor);
}
class ComputerPartDisplayVisitor implements ComputerPartVisitor {
@Override
public void visit(Keyboard keyboard) {
System.out.println("显示键盘");
}
@Override
public void visit(Monitor monitor) {
System.out.println("显示显示器");
}
}
public class Main {
public static void main(String[] args) {
ComputerPart[] parts = {new Keyboard(), new Monitor()};
ComputerPartVisitor visitor = new ComputerPartDisplayVisitor();
for (ComputerPart part : parts) {
part.accept(visitor);
}
}
}
18.2 状态模式
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
java复制interface State {
void handle(Context context);
}
class StartState implements State {
@Override
public void handle(Context context) {
System.out.println("处于开始状态");
context.setState(new RunningState());
}
}
class RunningState implements State {
@Override
public void handle(Context context) {
System.out.println("处于运行状态");
context.setState(new StopState());
}
}
class StopState implements State {
@Override
public void handle(Context context) {
System.out.println("处于停止状态");
context.setState(new StartState());
}
}
class Context {
private State state;
public Context() {
state = new StartState();
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}
public class Main {
public static void main(String[] args) {
Context context = new Context();
context.request();
context.request();
context.request();
context.request();
}
}
18.3 命令模式
命令模式将请求封装为对象,从而允许使用不同的请求、队列或日志来参数化其他对象,并支持可撤销的操作。
java复制interface Command {
void execute();
void undo();
}
class Light {
public void on() {
System.out.println("灯亮了");
}
public void off() {
System.out.println("灯灭了");
}
}
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}
public class Main {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton(); // 开灯
remote.pressUndo(); // 关灯
}
}
19. 多态与反射
反射机制可以与多态结合,实现更灵活的对象创建和方法调用。
19.1 通过反射创建对象
java复制interface Animal {
void makeSound();
}
class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("汪汪");
}
}
class Cat implements Animal {
@Override
public void makeSound() {
System.out.println("喵喵");
}
}
public class Main {
public static void main(String[] args) throws Exception {
String className = "Dog"; // 可以从配置读取
Class<?> clazz = Class.forName(className);
Animal animal = (Animal) clazz.getDeclaredConstructor().newInstance();
animal.makeSound();
}
}
19.2 动态代理
动态代理可以在运行时创建实现特定接口的代理类,常用于AOP编程。
java复制import java.lang.reflect.*;
interface Service {
void serve();
}
class RealService implements Service {
@Override
public void serve() {
System.out.println("实际服务执行");
}
}
class LoggingInvocationHandler implements InvocationHandler {
private final Object target;
public LoggingInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用方法前: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("调用方法后: " + method.getName());
return result;
}
}
public class Main {
public static void main(String[] args) {
Service realService = new RealService();
Service proxy = (Service) Proxy.newProxyInstance(
Service.class.getClassLoader(),
new Class[]{Service.class},
new LoggingInvocationHandler(realService)
);
proxy.serve();
}
}
20. 多态与函数式编程
现代Java版本引入了更多函数式编程特性,可以与多态结合使用。
20.1 函数式接口与多态
java复制import java.util.function.*;
public class Main {
public static void process(IntUnaryOperator operator, int value) {
int result = operator.applyAsInt(value);
System.out.println("结果: " + result);
}
public static void main(String[] args) {
// 使用Lambda表达式
