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

huangapple go评论72阅读模式
英文:

How to use Generics to simplify my Edit Method

问题

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;
英文:

In my program, I am trying to create a method that will Edit any property inside of a BaseContact. BaseContact is an abstract class that is extended within a PersonContact and BusinessContact classes. I want to create an edit method that asks the user what property they want to edit, shows them the old value, and then updates with the new value they want. I reuse a lot of code so I was thinking of trying to make another method that will help recycle code, but I'm unsure how that would work with the need of unique getters and setters.

public void editQuery() {
}
// Edit BaseContact
public void edit(int id) {
try {
contacts.contains(contacts.get(id - 1));
} catch (IndexOutOfBoundsException e) {
System.out.println(&quot;Contact does not exist\n--- EXIT ---&quot;);
return;
}
Boolean active = true;
// While Statement for Edit
while (active) {
System.out.println(
&quot;What property would you like to edit?\n1. Name\n2. Phone Number\n3. Date of Birth\n4. Hobby\n5. Description&quot;
+ &quot;\n6. Website URL\n7. Hours of Operation\n8. Street\n9. City\n10. State\n11. Zip Code\n12. Location&quot;
+ &quot;\n13. Relatives&quot; + &quot;\n14. Photos\n15. Exit&quot;);
String choice = sc.nextLine();
switch (choice.toUpperCase()) {
case &quot;1&quot;:
case &quot;NAME&quot;:
for (BaseContact contact : contacts) {
if (contact.getId() == id) {
System.out.println(&quot;Contact Name: &quot; + contact.getName() + &quot;\n&quot;);
System.out.print(&quot;New Name: &quot;);
String name = sc.nextLine();
contact.setName(name);
System.out.println(&quot;Contact Name Set To: &quot; + contact.getName());
}
}
break;
case &quot;3&quot;:
case &quot;DATE OF BIRTH&quot;:
for (BaseContact contact : contacts) {
if (contact.getId() == id) {
if (contact.getType().equals(&quot;personContact&quot;)) {
PersonContact temp = (PersonContact) contact;
System.out.println(&quot;Contact Date of Birth (ex. January 01, 1999): &quot; + temp.getDob() + &quot;\n&quot;);
System.out.print(&quot;New Date of Birth: &quot;);
String dob = sc.nextLine();
temp.setDob(dob);
System.out.println(&quot;Contact Date of Birth Set To: &quot; + temp.getDob());
}
}
}
break;
case &quot;10&quot;:
case &quot;STATE&quot;:
for (BaseContact contact : contacts) {
if (contact.getId() == id) {
System.out.println(&quot;Contact State: &quot; + contact.getLocation().getState());
System.out.print(&quot;New State: &quot;);
String state = sc.nextLine();
contact.getLocation().setState(state);
System.out.println(&quot;Contact State Set To: &quot; + contact.getLocation().getState());
}
}
break;
case &quot;12&quot;:
case &quot;LOCATION&quot;:
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(&quot;Contact Location Set To: &quot; + contact.getLocation());
}
}
break;
case &quot;13&quot;:
case &quot;RELATIVES&quot;:
for (BaseContact contact : contacts) {
if (contact.getId() == id) {
if (contact.getType().equals(&quot;personContact&quot;)) {
PersonContact temp = (PersonContact) contact;
System.out.println(&quot;List of Relatives&quot;);
System.out.print(&quot;Contact Relatives: &quot;);
for (int i = 0; i &lt; temp.getRelatives().size(); i++) {
System.out.println(temp.getRelatives().get(i).getName());
}
System.out.println(&quot;Would you like to 1. Add or 2. Remove relatives?&quot;);
String rChoice = sc.nextLine();
// Adding Relative
if (rChoice.equalsIgnoreCase(&quot;1&quot;) || rChoice.equalsIgnoreCase(&quot;ADD&quot;)) {
System.out.println(&quot;--- Add Relatives ---&quot;);
System.out.println(&quot;List of Available Contacts\n&quot;);
for (BaseContact rcontact : contacts) {
if (rcontact.getType().equals(&quot;personContact&quot;)) {
PersonContact rtemp = (PersonContact) rcontact;
System.out.print(rtemp.getName() + &quot; | &quot;);
}
}
System.out.println();
System.out.println(&quot;How many relatives would you like to add?&quot;);
int numOfRelatives = sc.nextInt();
sc.nextLine();
for (int i = 0; i &lt; numOfRelatives; i++) {
System.out.println(&quot;--- Add Relative ---&quot;);
System.out.print(&quot;Relative Name: &quot;);
String rname = sc.nextLine();
for (BaseContact r2contact : contacts) {
if (r2contact.getType().equals(&quot;personContact&quot;)) {
PersonContact r2temp = (PersonContact) r2contact;
if (rname.equalsIgnoreCase(r2temp.getName())) {
temp.getRelatives().add(r2temp);
}
}
}
}
// Removing Relative
} else if (rChoice.equals(&quot;2&quot;) || rChoice.equalsIgnoreCase(&quot;REMOVE&quot;)) {
System.out.println(&quot;--- Remove Relatives ---&quot;);
System.out.println(&quot;List of Relatives&quot;);
for (int i = 0; i &lt; temp.getRelatives().size(); i++) {
System.out.println(temp.getRelatives().get(i).getName());
}
System.out.println();
System.out.println(&quot;How many relatives would you like to remove?&quot;);
int numOfRelatives = sc.nextInt();
sc.nextLine();
if (numOfRelatives &gt; temp.getRelatives().size()
|| numOfRelatives == temp.getRelatives().size()) {
temp.getRelatives().clear();
System.out.println(&quot;All Relatives Removed&quot;);
} else {
for (int i = 0; i &lt; numOfRelatives; i++) {
System.out.println(&quot;--- Remove Relative ---&quot;);
System.out.print(&quot;Relative Name: &quot;);
String rName = sc.nextLine();
for (BaseContact r2contact : contacts) {
if (r2contact.getType().equals(&quot;personContact&quot;)) {
PersonContact r2temp = (PersonContact) r2contact;
if (rName.equalsIgnoreCase(r2temp.getName())) {
temp.getRelatives().remove(r2temp);
}
}
}
}
}
} else {
System.out.println(&quot;Invalid Option&quot;);
}
}
}
}
break;

答案1

得分: 0

好的,以下是翻译好的部分:

询问即将获得。我主要关注了你所编写的庞大的 switch 语句。首先,那应该被精简。更具功能性的编程风格可以在这里有所帮助。

我不得不根据代码中调用的方法推断出了你所使用的许多类。此外,我选择了一些 switch 表达式,并将它们转换为更具动态性的内容。将其视为在应用程序的其余部分进行构建的起点。

首先为简单编辑创建一个操作类:

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;
 }
}

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

  • actionText:用于标记正在编辑的属性。
  • action:接受两个参数并返回 void 的函数。
    在这种情况下,我们将使用它来在 PersonContact 上设置相应的值。
  • originalValFunc:从 PersonContact 中检索原始值的函数,它是一个带有一个参数(PersonContact)的函数,它返回一个字符串。

然后可以构建编辑方法如下:

class TestInputProgram {

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

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

//使用临时数据进行初始化
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())));
}};

// 编辑 BaseContact
public void edit(int id) {
    while (true) {
        System.out.println(
                "您想编辑哪个属性?\n" +
                        "1. 名称\n" +
                        "2. 电话号码\n" +
                        "3. 出生日期\n" +
                        "15. 退出");

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

        PersonContact pContact = contacts.stream()
                .filter(contact -> contact.id == id)
                .findFirst()
                .orElseThrow(
                        () -> new IllegalArgumentException("ID 为 " + id + " 的联系人不存在!")
                );

        Optional.ofNullable(actionMap.get(choice.toUpperCase())).ifPresent(actionHolder -> {
            System.out.println(actionHolder.getActionText() + " 当前值:"
                    + actionHolder.getOriginalValFunc().apply(pContact) + "\n");
            System.out.println("请输入新值:");
            String newValue = sc.nextLine();
            actionHolder.getAction().accept(newValue, pContact);
            System.out.println(actionHolder.getActionText() + " 设置为:"
                    + actionHolder.getOriginalValFunc().apply(pContact));
            System.out.println("############################# \n");
        });
    }
}
}

有关变量和正在进行的操作的一些简要信息:
actionMap 包含我们当前提供的所有可能的编辑选项。请注意,操作持有者参数的实现。我们使用 lambda 表达式和静态方法引用来实现操作。在 edit 方法内查询映射并检索 actionHolder。然后将相应的输入操作信息打印给用户并请求输入。使用来自 actionHolder 的 (BiConsumer) 处理输入。

希望这对未来的编程优化提供一些参考。

英文:

Well ask and thou shall receive. I have looked mainly at the humongous switch statement you have going on. For a starter, that should be condensed. A more functional style of programming can help here.

I had to deduce a lot of the classes you have used based on the methods which were called in the code. Furthermore, I have picked a couple of switch expressions and converted them in something more dynamic. See this as a starting point to build on for the rest of your application.

Start of with creating an action class for the simple edits:

public class ActionHolder {
private final String actionText;
private final BiConsumer&lt;String, PersonContact&gt; action;
private final Function&lt;PersonContact, String&gt; originalValFunc;
public ActionHolder(String actionText, BiConsumer&lt;String, PersonContact&gt; action,
Function&lt;PersonContact, String&gt; originalValFunc) {
this.actionText = actionText;
this.action = action;
this.originalValFunc = originalValFunc;
}
public String getActionText() {
return actionText;
}
public BiConsumer&lt;String, PersonContact&gt; getAction() {
return action;
}
public Function&lt;PersonContact, String&gt; getOriginalValFunc() {
return originalValFunc;
}
}

The action class relies heavily on functional interfaces, make sure you read up on them thoroughly as they provide a powerful way of programming. (https://www.baeldung.com/java-8-functional-interfaces)

  • actionText: Is used to label the attribute which is edited.
  • action: A function which accepts two arguments and returns nothing.
    In this case we will use this to set the respective value on the
    PersonContact
  • originalValFunc: A function to retrieve the origional value from the
    PersonContact, it is a function with one parameter (PersonContact)
    and it returns a string.

The edit method can then be build up as follows:

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&lt;PersonContact&gt; contacts = new ArrayList&lt;PersonContact&gt;() {{
add(new PersonContact(1));
}};
private static final Map&lt;String, ActionHolder&gt; actionMap = new HashMap&lt;String, ActionHolder&gt;() {{
put(&quot;1&quot;, new ActionHolder(&quot;Contact Name&quot;,
(input, contact) -&gt; contact.setName(input), BaseContact::getName));
put(&quot;NAME&quot;, new ActionHolder(&quot;Contact Name&quot;,
(input, contact) -&gt; contact.setName(input), BaseContact::getName));
put(&quot;3&quot;, new ActionHolder(&quot;Date of Birth&quot;,
(input, contact) -&gt; contact.setDob(input), PersonContact::getDob));
put(&quot;DATE OF BIRTH&quot;, new ActionHolder(&quot;Date of Birth&quot;,
(input, contact) -&gt; contact.setDob(input), PersonContact::getDob));
put(&quot;10&quot;, new ActionHolder(&quot;State&quot;,
(input, contact) -&gt; contact.getLocation().setState(input),
(contact -&gt; contact.getLocation().getState())));
put(&quot;STATE&quot;, new ActionHolder(&quot;State&quot;,
(input, contact) -&gt; contact.getLocation().setState(input),
(contact -&gt; contact.getLocation().getState())));
}};
// Edit BaseContact
public void edit(int id) {
while (true) {
System.out.println(
&quot;What property would you like to edit?\n&quot; +
&quot;1. Name\n&quot; +
&quot;2. Phone Number\n&quot; +
&quot;3. Date of Birth\n&quot; +
&quot;15. Exit&quot;);
String choice = sc.nextLine();
if (Objects.equals(choice, &quot;15&quot;)) {
break;
}
PersonContact pContact = contacts.stream()
.filter(contact -&gt; contact.id == id)
.findFirst()
.orElseThrow(
() -&gt; new IllegalArgumentException(&quot;Contact with id: &quot; + id + &quot; does not exist!&quot;)
);
Optional.ofNullable(actionMap.get(choice.toUpperCase())).ifPresent(actionHolder -&gt; {
System.out.println(actionHolder.getActionText() + &quot; current value: &quot;
+ actionHolder.getOriginalValFunc().apply(pContact) + &quot;\n&quot;);
System.out.println(&quot;Please provide the new value:&quot;);
String newValue = sc.nextLine();
actionHolder.getAction().accept(newValue, pContact);
System.out.println(actionHolder.getActionText() + &quot; set to: &quot;
+ actionHolder.getOriginalValFunc().apply(pContact));
System.out.println(&quot;############################# \n&quot;);
});
}
}
}

Some brief info about the variables and whats going on:
The actionMap holds all the possible edit options we currently provide. Notice the implementation of the action holder arguments. We implement the actions using both lamda's and static method references. Inside the edit method the map is queried and the actionHolder retrieved. The respective input action info is then printed to the user and asked for input. The input is processed using the (BiConsumer) from the actionHolder.

I hope this will provide some reference for future programming optimization.

huangapple
  • 本文由 发表于 2020年10月7日 01:03:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/64230577.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定