You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于基类枚举实现页面类方法复用 消除代码冗余

Refactoring goToParticularTableSection to a Base Class (Eliminating Duplication)

Great question! This is a perfect opportunity to leverage abstraction, generics, and interfaces to pull that repetitive switch logic into a reusable base class. Here's how to do it cleanly:


Step 1: Create a Common Interface for Section Enums

First, define a shared interface that all your page-specific section enums will implement. This lets the base class treat any section enum uniformly:

public interface TableSection {
    // Optional: Add a method to get a human-readable name for logging
    default String getSectionName() {
        return this.toString();
    }
}

Step 2: Update Your Page-Specific Enums

Modify each of your existing section enums to implement this interface. For example:

// For your Draggable page
public enum TableSectionDraggablePage implements TableSection {
    DefaultFunctionality,
    ConstrainMovement,
    // Add other sections here
}

// For another page (e.g., Sortable)
public enum TableSectionSortablePage implements TableSection {
    SortableLists,
    GridSorting
}

Step 3: Build the Reusable Base Page Class

Create an abstract base class that uses generics to work with any enum implementing TableSection. The base class will handle the common logic (clicking, logging), while forcing subclasses to provide the mapping between enum values and their corresponding UI elements:

public abstract class BasePage<T extends Enum<T> & TableSection> {
    // Assume your base class already has common utilities like clickOnElement, TestLogger, etc.
    protected abstract Map<T, WebElement> getSectionElementMap();

    public void goToParticularTableSection(T targetSection) {
        // Fetch the element from the subclass-provided map
        WebElement sectionHeader = getSectionElementMap().get(targetSection);
        
        // Guard against invalid sections to avoid NPEs
        if (sectionHeader == null) {
            throw new IllegalArgumentException("Unknown section: " + targetSection.getSectionName());
        }

        // Reuse your existing click logic
        clickOnElement(sectionHeader);
        TestLogger.log.info(targetSection.getSectionName() + " clicked");
    }

    // If you don't already have this in a base class, add it here
    protected void clickOnElement(WebElement element) {
        element.click();
        // Add waits or other common click logic here if needed
    }
}

Step 4: Implement the Mapping in Your Concrete Page Classes

Each page class will extend the base class, specify its corresponding enum type, and provide the mapping between enum values and page elements:

public class DraggablePage extends BasePage<TableSectionDraggablePage> {
    // Your page elements (initialized via PageFactory or similar)
    @FindBy(id = "default-functionality-header")
    private WebElement defaultFunctionalityTableHeader;

    @FindBy(id = "constrain-movement-header")
    private WebElement constraintMovementTableHeader;

    @Override
    protected Map<TableSectionDraggablePage, WebElement> getSectionElementMap() {
        Map<TableSectionDraggablePage, WebElement> sectionMap = new HashMap<>();
        sectionMap.put(TableSectionDraggablePage.DefaultFunctionality, defaultFunctionalityTableHeader);
        sectionMap.put(TableSectionDraggablePage.ConstrainMovement, constraintMovementTableHeader);
        // Add mappings for other sections here
        return sectionMap;
    }
}

Step 5: Use the Refactored Code

Now you can call the method exactly like before, but the logic is centralized in the base class:

DraggablePage draggablePage = new DraggablePage();
draggablePage.goToParticularTableSection(TableSectionDraggablePage.DefaultFunctionality);

Alternative Optimization: Bind Locators Directly to Enums

If you prefer not to maintain a Map in each page, you can modify the TableSection interface to hold element locators (like By objects) directly. This keeps the enum and its UI binding tightly coupled:

  1. Update the interface:
public interface TableSection {
    By getLocator();
    default String getSectionName() {
        return this.toString();
    }
}
  1. Update the enum to include locators:
public enum TableSectionDraggablePage implements TableSection {
    DefaultFunctionality(By.id("default-functionality-header")),
    ConstrainMovement(By.id("constrain-movement-header"));

    private final By locator;

    TableSectionDraggablePage(By locator) {
        this.locator = locator;
    }

    @Override
    public By getLocator() {
        return locator;
    }
}
  1. Simplify the base class:
public abstract class BasePage<T extends Enum<T> & TableSection> {
    protected WebDriver driver;

    public BasePage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }

    public void goToParticularTableSection(T targetSection) {
        WebElement sectionHeader = driver.findElement(targetSection.getLocator());
        clickOnElement(sectionHeader);
        TestLogger.log.info(targetSection.getSectionName() + " clicked");
    }

    protected void clickOnElement(WebElement element) {
        element.click();
    }
}

This approach eliminates the need for per-page Maps entirely, which can be cleaner if your elements are located dynamically rather than via PageFactory.


内容的提问来源于stack exchange,提问作者Dawid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:01:29