面试题答案
一键面试类结构设计
- 抽象产品类:定义所有具体产品类(模块相关对象)的公共接口。例如:
public interface Product {
void execute();
}
- 具体产品类:实现抽象产品类接口,对应各个低耦合模块中的具体对象。例如:
public class ConcreteProductA implements Product {
@Override
public void execute() {
System.out.println("ConcreteProductA is executing.");
}
}
public class ConcreteProductB implements Product {
@Override
public void execute() {
System.out.println("ConcreteProductB is executing.");
}
}
- 抽象工厂类:定义创建产品对象的抽象方法。
public abstract class AbstractFactory {
public abstract Product createProduct();
}
- 具体工厂类:继承抽象工厂类,实现创建具体产品对象的方法。
public class ConcreteFactoryA extends AbstractFactory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
public class ConcreteFactoryB extends AbstractFactory {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
反射的具体应用
- 通过配置文件获取类名:在实际应用中,可以通过配置文件(如properties文件)来存储具体产品类和具体工厂类的全限定名。例如:
productA.class=com.example.ConcreteProductA
productB.class=com.example.ConcreteProductB
factoryA.class=com.example.ConcreteFactoryA
factoryB.class=com.example.ConcreteFactoryB
- 利用反射创建对象:在工厂类的创建方法中,通过反射机制根据配置文件中的类名创建对象。以抽象工厂类的创建方法修改为例:
public abstract class AbstractFactory {
public abstract Product createProduct();
protected Product createProductByReflection(String className) {
try {
Class<?> productClass = Class.forName(className);
return (Product) productClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
具体工厂类实现:
public class ConcreteFactoryA extends AbstractFactory {
@Override
public Product createProduct() {
return createProductByReflection("com.example.ConcreteProductA");
}
}
工厂模式的选型
这里选用工厂方法模式。原因如下:
- 简单工厂模式:不符合开闭原则,每次添加新的产品类都需要修改工厂类的创建逻辑。
- 工厂方法模式:符合开闭原则,每个具体产品类都有对应的具体工厂类,新增产品类时,只需要新增对应的具体工厂类,无需修改现有工厂类代码,适合本系统可扩展性需求。
- 抽象工厂模式:适用于创建一系列相关产品对象的场景,而本系统中模块间耦合度低,产品对象相对独立,不需要创建一系列相关产品,故不适合。
处理模块间的依赖关系
- 通过接口依赖:模块之间通过抽象产品类(接口)进行依赖,而不是直接依赖具体产品类。这样可以降低模块间的耦合度,提高系统的灵活性。例如,某个模块中使用产品对象的代码如下:
public class Module {
private Product product;
public Module(Product product) {
this.product = product;
}
public void doSomething() {
product.execute();
}
}
- 依赖注入:在创建模块对象时,通过构造函数或其他方式将所需的产品对象注入到模块中。例如:
AbstractFactory factory = new ConcreteFactoryA();
Product product = factory.createProduct();
Module module = new Module(product);
module.doSomething();
通过这种方式,模块之间的依赖关系由外部(工厂)进行管理,进一步提高了系统的可维护性和灵活性。