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

如何通过Product实体对象调用服务方法?是否需继承实体类?

问题

我有一个名为Product的实体类,定义如下:

public String email;
public int age;
public double price;
public double discount;

我想为它创建一个服务类来实现计算逻辑,请问是否需要继承Product类来使用email、age、price等变量进行计算?另外,我是否必须创建服务类对象,还是可以通过Product实体对象直接调用服务方法?

目前我的main方法中是这样创建服务对象的:
Service service = new Service("email", 1, 30)
但我希望能创建Product实体对象,再通过该对象调用服务方法,即:
Product product = new Product ("email", 1, 30)


现有代码示例

Main类

public class Main {

public static void main(String[] args) {

    Scanner scanner = new Scanner(System.in);
    TaxService taxService = new TaxService("The Little Prince", 12345, 20.25);

    int option = 0;
    do {
        menu();
        option = scanner.nextInt();
        switch (option) {
            case 1:
                taxService.tax();
                break;
            case 2:
                System.out.println(
                        "\nThank you for using the program. Goodbye!\n");
                System.exit(0);

                break;
            default:
                System.out.println("Invalid input");
                break;
        }
    } while (option != 9);
}


public static void menu() {
    System.out.println("Choose action");
    System.out.println("1. Tax calculate\n");
    System.out.println("2: Exit program");


    System.out.print("Enter your selection: ");
}
}

Product实体类

public class Product {
public String name;
public int UPC;
public double price;
public double tax;


public Product() {
}

public Product(String name, int UPC, double price) {
    this.name = name;
    this.UPC = UPC;
    this.price = price;
    this.tax = 20;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getUPC() {
    return UPC;
}

public void setUPC(int UPC) {
    this.UPC = UPC;
}

public double getPrice() {
    return price;
}

public void setPrice(double price) {
    this.price = price;
}

public double getTax() {
    return tax;
}

public void setTax(double tax) {
    this.tax = tax;
}
}

TaxService服务类

public class TaxService extends Product {

Scanner scanner = new Scanner(System.in);

public TaxService(String name, int UPC, double price) {
    super(name, UPC, price);
}

public void tax() {
    System.out.println("Do you want to change tax percentage? (y / n)");
    String answer = scanner.nextLine();

    if (answer.equalsIgnoreCase("y")) {
        System.out.println("Please enter a new tax percentage: ");
        double newTaxPercentage = scanner.nextInt();
        scanner.nextLine();
        if (newTaxPercentage < 0) {
            System.out.println("Wrong input, try again.");
        } else {
            double calculateTax = (price * (newTaxPercentage / 100));
            double result = calculateTax + price;
            System.out.println("Calculation finished");
            System.out.printf("Product price reported as $%.2f before tax and $%.2f after %.0f%% tax.\n", price, result, newTaxPercentage);
        }
    } else {
        double calculateTax = (price * (tax / 100));
        double result = calculateTax + price;
        System.out.println("Calculation finished");
        System.out.printf("Product price reported as $%.2f before tax and $%.2f after %.0f%% tax.\n", price, result, tax);
    }
}

private boolean isTaxValid() {
    return tax < 0;
}
}

解答

1. 是否需要继承Product类?

不需要。继承的核心是**"is-a"**关系(比如Dog extends Animal表示狗是一种动物),但TaxService显然不是一种Product,强行继承会违背面向对象的设计原则,还会让代码耦合性过高。

正确的做法是依赖注入:在服务类中接收Product对象作为参数,通过它的get方法访问属性。这样既符合单一职责原则(Product负责存储数据,Service负责计算逻辑),也让代码更易维护和扩展。

2. 能否通过Product对象直接调用服务方法?

两种方式都可行,分场景选择:

  • 如果想让业务逻辑和实体数据解耦,保持Product的纯粹性(只负责存储数据),就保留独立的服务类,通过服务类接收Product对象执行计算。
  • 如果计算逻辑是Product的固有行为(比如计算最终售价),也可以把方法直接写在Product类里,这样就能直接用Product对象调用。但这种方式会让实体类承担业务逻辑,适合简单场景。

代码改造示例

改造后的TaxService(不继承,依赖Product)

public class TaxService {
    private Scanner scanner = new Scanner(System.in);

    // 接收Product对象作为参数,通过get方法访问属性
    public void calculateTax(Product product) {
        System.out.println("Do you want to change tax percentage? (y / n)");
        String answer = scanner.nextLine();

        if (answer.equalsIgnoreCase("y")) {
            System.out.println("Please enter a new tax percentage: ");
            double newTaxPercentage = scanner.nextInt();
            scanner.nextLine();
            if (newTaxPercentage < 0) {
                System.out.println("Wrong input, try again.");
                return;
            }
            double calculateTax = product.getPrice() * (newTaxPercentage / 100);
            double result = calculateTax + product.getPrice();
            System.out.println("Calculation finished");
            System.out.printf("Product price reported as $%.2f before tax and $%.2f after %.0f%% tax.\n", 
                product.getPrice(), result, newTaxPercentage);
            // 可选:更新产品的税率
            product.setTax(newTaxPercentage);
        } else {
            double calculateTax = product.getPrice() * (product.getTax() / 100);
            double result = calculateTax + product.getPrice();
            System.out.println("Calculation finished");
            System.out.printf("Product price reported as $%.2f before tax and $%.2f after %.0f%% tax.\n", 
                product.getPrice(), result, product.getTax());
        }
    }
}

改造后的Main方法(先创建Product,再传给服务类)

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 先创建Product实体对象
        Product product = new Product("The Little Prince", 12345, 20.25);
        // 创建服务类对象
        TaxService taxService = new TaxService();

        int option = 0;
        do {
            menu();
            option = scanner.nextInt();
            scanner.nextLine(); // 处理输入后的换行符
            switch (option) {
                case 1:
                    // 把Product对象传给服务方法执行计算
                    taxService.calculateTax(product);
                    break;
                case 2:
                    System.out.println("\nThank you for using the program. Goodbye!\n");
                    System.exit(0);
                default:
                    System.out.println("Invalid input");
                    break;
            }
        } while (option != 2); // 修正循环条件,和菜单选项保持一致
    }

    public static void menu() {
        System.out.println("Choose action");
        System.out.println("1. Tax calculate");
        System.out.println("2: Exit program");
        System.out.print("Enter your selection: ");
    }
}

额外优化点

  • 原代码中Product的属性是public的,建议改为private,通过get/set方法访问,符合封装原则。
  • 服务类里的Scanner可以在Main中创建后传入,避免重复创建实例。
  • 原Main方法的循环条件option !=9和菜单选项不符,改成option !=2更合理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:48:14