如何使用泛型来简化我的编辑方法

How to use Generics to simplify my Edit Method

在我的程序中,我试图创建一个方法来编辑 BaseContact 中的任何 属性。 BaseContact 是在 PersonContact 和 BusinessContact class 中扩展的抽象 class。我想创建一个编辑方法,询问用户 属性 他们想要编辑什么,向他们显示旧值,然后更新为他们想要的新值。我重用了很多代码,所以我在考虑尝试制作另一种有助于回收代码的方法,但我不确定这将如何满足独特的 getter 和 setter 的需要。

public void editQuery() {
    
}

// Edit BaseContact
public void edit(int id) {
    try {
        contacts.contains(contacts.get(id - 1));
    } catch (IndexOutOfBoundsException e) {
        System.out.println("Contact does not exist\n--- EXIT ---");
        return;
    }
    Boolean active = true;

    // While Statement for Edit
    while (active) {
        System.out.println(
                "What property would you like to edit?\n1. Name\n2. Phone Number\n3. Date of Birth\n4. Hobby\n5. Description"
                        + "\n6. Website URL\n7. Hours of Operation\n8. Street\n9. City\n10. State\n11. Zip Code\n12. Location"
                        + "\n13. Relatives" + "\n14. Photos\n15. Exit");

        String choice = sc.nextLine();
        switch (choice.toUpperCase()) {

        case "1":
        case "NAME":
            for (BaseContact contact : contacts) {
                if (contact.getId() == id) {
                    System.out.println("Contact Name: " + contact.getName() + "\n");
                    System.out.print("New Name: ");
                    String name = sc.nextLine();
                    contact.setName(name);
                    System.out.println("Contact Name Set To: " + contact.getName());
                }
            }
            break;
        case "3":
        case "DATE OF BIRTH":
            for (BaseContact contact : contacts) {
                if (contact.getId() == id) {
                    if (contact.getType().equals("personContact")) {
                        PersonContact temp = (PersonContact) contact;
                        System.out.println("Contact Date of Birth (ex. January 01, 1999): " + temp.getDob() + "\n");
                        System.out.print("New Date of Birth: ");
                        String dob = sc.nextLine();
                        temp.setDob(dob);
                        System.out.println("Contact Date of Birth Set To: " + temp.getDob());
                    }
                }
            }
            break;
        case "10":
        case "STATE":
            for (BaseContact contact : contacts) {
                if (contact.getId() == id) {
                    System.out.println("Contact State: " + contact.getLocation().getState());
                    System.out.print("New State: ");
                    String state = sc.nextLine();
                    contact.getLocation().setState(state);
                    System.out.println("Contact State Set To: " + contact.getLocation().getState());
                }
            }
            break;
        case "12":
        case "LOCATION":
            for (BaseContact contact : contacts) {
                if (contact.getId() == id) {
                    // Location
                    Location location = createLocation();
                    contact.getLocation().setStreet(location.getStreet());
                    contact.getLocation().setCity(location.getCity());
                    contact.getLocation().setState(location.getState());
                    contact.getLocation().setZipCode(location.getZipCode());
                    System.out.println("Contact Location Set To: " + contact.getLocation());
                }
            }
            break;

        case "13":
        case "RELATIVES":
            for (BaseContact contact : contacts) {
                if (contact.getId() == id) {
                    if (contact.getType().equals("personContact")) {
                        PersonContact temp = (PersonContact) contact;
                        System.out.println("List of Relatives");
                        System.out.print("Contact Relatives: ");
                        for (int i = 0; i < temp.getRelatives().size(); i++) {
                            System.out.println(temp.getRelatives().get(i).getName());
                        }
                        System.out.println("Would you like to 1. Add or 2. Remove relatives?");
                        String rChoice = sc.nextLine();
                        // Adding Relative
                        if (rChoice.equalsIgnoreCase("1") || rChoice.equalsIgnoreCase("ADD")) {
                            System.out.println("--- Add Relatives ---");
                            System.out.println("List of Available Contacts\n");
                            for (BaseContact rcontact : contacts) {
                                if (rcontact.getType().equals("personContact")) {
                                    PersonContact rtemp = (PersonContact) rcontact;
                                    System.out.print(rtemp.getName() + " | ");
                                }
                            }
                            System.out.println();
                            System.out.println("How many relatives would you like to add?");
                            int numOfRelatives = sc.nextInt();
                            sc.nextLine();
                            for (int i = 0; i < numOfRelatives; i++) {
                                System.out.println("--- Add Relative ---");
                                System.out.print("Relative Name: ");
                                String rname = sc.nextLine();
                                for (BaseContact r2contact : contacts) {
                                    if (r2contact.getType().equals("personContact")) {
                                        PersonContact r2temp = (PersonContact) r2contact;
                                        if (rname.equalsIgnoreCase(r2temp.getName())) {
                                            temp.getRelatives().add(r2temp);
                                        }
                                    }
                                }
                            }
                            // Removing Relative
                        } else if (rChoice.equals("2") || rChoice.equalsIgnoreCase("REMOVE")) {
                            System.out.println("--- Remove Relatives ---");
                            System.out.println("List of Relatives");
                            for (int i = 0; i < temp.getRelatives().size(); i++) {
                                System.out.println(temp.getRelatives().get(i).getName());
                            }
                            System.out.println();
                            System.out.println("How many relatives would you like to remove?");
                            int numOfRelatives = sc.nextInt();
                            sc.nextLine();
                            if (numOfRelatives > temp.getRelatives().size()
                                    || numOfRelatives == temp.getRelatives().size()) {
                                temp.getRelatives().clear();
                                System.out.println("All Relatives Removed");
                            } else {
                                for (int i = 0; i < numOfRelatives; i++) {
                                    System.out.println("--- Remove Relative ---");
                                    System.out.print("Relative Name: ");
                                    String rName = sc.nextLine();
                                    for (BaseContact r2contact : contacts) {
                                        if (r2contact.getType().equals("personContact")) {
                                            PersonContact r2temp = (PersonContact) r2contact;
                                            if (rName.equalsIgnoreCase(r2temp.getName())) {
                                                temp.getRelatives().remove(r2temp);
                                            }
                                        }
                                    }
                                }
                            }
                        } else {
                            System.out.println("Invalid Option");
                        }
                    }
                }
            }
            break;

好吧,你会得到的。我主要查看了您正在进行的巨大的 switch 语句。对于初学者来说,这应该是浓缩的。更函数式的编程风格可以提供帮助。

我不得不根据代码中调用的方法推断出您使用的许多 classes。此外,我还挑选了几个 switch 表达式并将它们转换为更动态的内容。将此视为构建应用程序其余部分的起点。

开始为简单编辑创建操作 class:

public class ActionHolder {
 private final String actionText;
 private final BiConsumer<String, PersonContact> action;
 private final Function<PersonContact, String> originalValFunc;

 public ActionHolder(String actionText, BiConsumer<String, PersonContact> action,
                    Function<PersonContact, String> originalValFunc) {
     this.actionText = actionText;
     this.action = action;
     this.originalValFunc = originalValFunc;
 }

 public String getActionText() {
     return actionText;
 }

 public BiConsumer<String, PersonContact> getAction() {
     return action;
 }

 public Function<PersonContact, String> getOriginalValFunc() {
     return originalValFunc;
 }
}

操作 class 在很大程度上依赖于函数式接口,请确保您通读它们,因为它们提供了一种强大的编程方式。 (https://www.baeldung.com/java-8-functional-interfaces)

  • actionText:用于标记被编辑的属性。
  • action:接受两个参数且 returns 什么都不接受的函数。 在这种情况下,我们将使用它来设置相应的值 联系人
  • originalValFunc:从中检索原始值的函数 PersonContact,它是一个带一个参数的函数(PersonContact) 它 returns 一个字符串。

编辑方法可以构建如下:

class TestInputProgram {

public static void main(String[] args) {
    TestInputProgram inputProgram = new TestInputProgram();
    inputProgram.edit(1);
}

private final Scanner sc = new Scanner(System.in);

//Initialize with temp data
private final ArrayList<PersonContact> contacts = new ArrayList<PersonContact>() {{
    add(new PersonContact(1));
}};

private static final Map<String, ActionHolder> actionMap = new HashMap<String, ActionHolder>() {{
    put("1", new ActionHolder("Contact Name",
            (input, contact) -> contact.setName(input), BaseContact::getName));
    put("NAME", new ActionHolder("Contact Name",
            (input, contact) -> contact.setName(input), BaseContact::getName));
    put("3", new ActionHolder("Date of Birth",
            (input, contact) -> contact.setDob(input), PersonContact::getDob));
    put("DATE OF BIRTH", new ActionHolder("Date of Birth",
            (input, contact) -> contact.setDob(input), PersonContact::getDob));
    put("10", new ActionHolder("State",
            (input, contact) -> contact.getLocation().setState(input),
            (contact -> contact.getLocation().getState())));
    put("STATE", new ActionHolder("State",
            (input, contact) -> contact.getLocation().setState(input),
            (contact -> contact.getLocation().getState())));
}};

// Edit BaseContact
public void edit(int id) {
    while (true) {
        System.out.println(
                "What property would you like to edit?\n" +
                        "1. Name\n" +
                        "2. Phone Number\n" +
                        "3. Date of Birth\n" +
                        "15. Exit");

        String choice = sc.nextLine();
        if (Objects.equals(choice, "15")) {
            break;
        }

        PersonContact pContact = contacts.stream()
                .filter(contact -> contact.id == id)
                .findFirst()
                .orElseThrow(
                        () -> new IllegalArgumentException("Contact with id: " + id + " does not exist!")
                );

        Optional.ofNullable(actionMap.get(choice.toUpperCase())).ifPresent(actionHolder -> {
            System.out.println(actionHolder.getActionText() + " current value: "
                    + actionHolder.getOriginalValFunc().apply(pContact) + "\n");
            System.out.println("Please provide the new value:");
            String newValue = sc.nextLine();
            actionHolder.getAction().accept(newValue, pContact);
            System.out.println(actionHolder.getActionText() + " set to: "
                    + actionHolder.getOriginalValFunc().apply(pContact));
            System.out.println("############################# \n");
        });
    }
}
}

关于变量和发生的事情的一些简要信息: actionMap 包含我们当前提供的所有可能的编辑选项。注意操作持有者参数的实现。我们使用 lamda 和静态方法引用来实现操作。在 edit 方法中查询地图并检索 actionHolder。然后将相应的输入操作信息打印给用户并要求输入。使用来自 actionHolder 的 (BiConsumer) 处理输入。

希望能为以后的编程优化提供一些参考。