利用多态性设计灵活可扩展系统架构
- 实现接口或继承抽象类示例
// 定义接口
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 InterfacePolymorphismExample {
public static void main(String[] args) {
Shape circle = new Circle(5);
Shape rectangle = new Rectangle(4, 6);
System.out.println("Circle area: " + circle.getArea());
System.out.println("Rectangle area: " + rectangle.getArea());
}
}
// 定义抽象类
abstract class Animal {
abstract void makeSound();
}
// 继承抽象类的具体类
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Woof!");
}
}
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Meow!");
}
}
// 测试多态性
public class AbstractClassPolymorphismExample {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
dog.makeSound();
cat.makeSound();
}
}
- 抽象类和接口在多态性实现中的不同表现及优势
- 不同表现
- 抽象类:可以有成员变量和具体方法,子类继承抽象类,是一种“is - a”关系。抽象类的成员变量可以被子类继承和使用,具体方法可以在子类中直接复用。
- 接口:只有抽象方法(Java 8 后可包含默认方法和静态方法),类实现接口,是一种“like - a”关系。接口主要用于定义行为规范,实现接口的类必须实现其所有抽象方法(除默认方法外)。
- 优势
- 抽象类:适合提取具有共同属性和行为的类的共性,方便代码复用。例如,在图形绘制系统中,抽象类可以定义图形的一些通用属性和操作,如颜色、位置等,以及一些通用的绘制方法框架。
- 接口:适合实现多继承,使一个类可以同时具有多种行为。例如,在一个游戏角色系统中,一个角色类可以同时实现“Moveable”接口(表示可移动行为)、“Attackable”接口(表示可攻击行为)等。
高并发场景下多态性应用的问题及解决方案
- 问题
- 线程安全问题:如果实现接口或继承抽象类的类中有共享资源且方法不是线程安全的,在高并发情况下可能出现数据竞争。例如,一个实现了接口的计数器类,多个线程同时调用其计数方法可能导致计数不准确。
- 性能问题:多态性的实现通常涉及方法的动态绑定,在高并发场景下频繁的动态绑定可能带来一定的性能开销。
- 解决方案
- 线程安全问题解决方案
- 同步机制:使用
synchronized
关键字对共享资源的访问方法进行同步。例如:
class SafeCounter implements Runnable {
private int count = 0;
public synchronized void increment() {
count++;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
increment();
}
}
}
- **使用线程安全类**:如`java.util.concurrent.atomic`包下的原子类,`AtomicInteger`等。
import java.util.concurrent.atomic.AtomicInteger;
class AtomicSafeCounter implements Runnable {
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet();
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
increment();
}
}
}
- 性能问题解决方案
- 缓存方法调用:如果某些方法调用频率高且结果不经常变化,可以缓存方法调用结果。
- 减少动态绑定:在设计时尽量将不变的行为放到具体类的静态方法中,避免不必要的动态绑定。例如,如果某个图形计算面积的方法在高并发下频繁调用且图形参数不变,可以将该计算方法设计为静态方法。