简体   繁体   English

Java 通用/工厂枚举

[英]Java Generic / Enum in Factory

I have studying Java, and wanna understand how to realize idea of such factory of products?我正在研究 Java,想了解如何实现这种产品工厂的想法? (or other way structure of code) (或其他方式的代码结构)

public interface  VirtualBD <E extends Enum<E>>  {  
    void addInStorage(Class<E> type, Product product, int amount);
}

1 Question: how to use generic to get any type of Enum class as parameter 1 问:如何使用泛型获取任何类型的枚举 class 作为参数

Root Categorie根类别

public abstract class Product { 
    ...
}
public enum AlchogolType {
    Beer, Vodka;
}
public enum nonAlchogolType {
    FreshJuise, Lemonade;
}

SubCategories子类别

public abstract class Alchogol extends Product {
    ...
}
public abstract class nonAlchogol extends Product {
    ...
}
public class Beer extends Alchogol {
    ...
}

And, here is a problem begin's:而且,这里有一个问题开始:

public class AlchogolTables implements VirtualBD{

    HashMap<Alchogol, Integer> beer = new HashMap<Alchogol, Integer>();
    HashMap<Alchogol, Integer> vodka = new HashMap<Alchogol, Integer>();

    @Override
    public void addInStorage(AlchogolType type, Product product, int amount) {
        switch (type) {
        case Beer:
            beer.put((Alchogol) product,amount);
            break;

        case Vodka:
            vodka.put((Alchogol) product,amount);
            break;
            
        default:
            break;
        }
        
    }

}

in my idea - i want to use addInStorage method for different products, like:在我的想法中-我想对不同的产品使用addInStorage方法,例如:

public class OtherBeveragesTables implements VirtualBD{

    HashMap<nonAlchogol, Integer> orangeFresh = new HashMap<nonAlchogol, Integer>();
    HashMap<nonAlchogol, Integer> soda = new HashMap<nonAlchogol, Integer>();

@Override
    public void addInStorage(nonAlchogolType type, Product product, int amount) {
        switch (type) {
        case FreshJuise:
            orangeFresh.put((nonAlchogol) product,amount);
            break;

        case Lemonade:
            soda.put((nonAlchogol) product,amount);
            break;
            
        default:
            break;
        }
        
    }

}
  1. how can i use Enum AlchogolType/nonAlchogolType as parametr?我如何使用 Enum AlchogolType/nonAlchogolType 作为参数?
  2. I doubt the correctness of the organization of the code for such a task as: writing a factory for many products with categories, some differences and similarities.我怀疑这样一个任务的代码组织的正确性:为许多具有类别、一些差异和相似之处的产品编写工厂。
  3. Is a CAST: beer.put((Alchogol) product,amount);是一个 CAST: beer.put((Alchogol) product,amount); normal way?正常方式?

Question 1问题 1

"how can i use Enum AlchogolType/nonAlchogolType as parametr?" “我如何使用 Enum AlchogolType/nonAlchogolType 作为参数?”

When reading your question, I assume that you are looking for a way on how you can pass both AlchogolType and NonAlchogolType as parameter in the same method.在阅读您的问题时,我假设您正在寻找一种方法来在同一方法中将 AlchogolType 和 NonAlchogolType 作为参数传递。 Unfortunately this is not possible, since a method asks for a specific type.不幸的是,这是不可能的,因为方法要求特定类型。 Unlike classes, enums cannot override from other classes/enums.与类不同,枚举不能覆盖其他类/枚举。 This means that the parameter type given in the method cannot be anything else than that.这意味着方法中给出的参数类型不能是其他任何东西。

Let's say there is EnumOne (APPLE, BANANA, PINEAPPLE) and EnumTwo (AUDI, BWM, FORD).假设有EnumOne (APPLE, BANANA, PINEAPPLE) 和EnumTwo (AUDI, BWM, FORD)。 If a method asks for a parameter of type EnumOne there is no way of passing anything else that is not defined in the EnumOne enum.如果一个方法请求EnumOne类型的参数,则无法传递EnumOne枚举中未定义的任何其他内容。 You will get compiler errors when trying to pass values from, let's say, EnumTwo .尝试从EnumTwo传递值时,您会遇到编译器错误。

If you would like to have a work-around for this, you can try and put the values in one enum class.如果您想解决此问题,可以尝试将这些值放在一个枚举 class 中。 Only do this if your code can still remain maintainable and efficient.仅当您的代码仍然可以保持可维护性和高效性时才这样做。

Question 2问题2

"I doubt the correctness of the organization of the code for such a task as: writing a factory for many products with categories, some differences and similarities." “我怀疑这样一个任务的代码组织的正确性:为许多具有类别、一些差异和相似之处的产品编写工厂。”

Even though you are using abstraction to divide logic from your models in your code, you are still using separate classes (VirtualDB classes in your case) that prevent your program from using the benefits of abstraction in Object-oriented-programming.即使您在代码中使用抽象将逻辑与模型分开,您仍然使用单独的类(在您的情况下为 VirtualDB 类),这会阻止您的程序在面向对象编程中使用抽象的好处。

Using abstractions in your model classes (Beer in your case), is good.在您的 model 类(在您的情况下为啤酒)中使用抽象是好的。 I would recommend keeping it like that and not go further with applying abstraction in combination with your factory classes.我建议保持这种状态,而不是 go 进一步结合您的工厂类应用抽象。

I believe you only need 1 factory class that holds all of your products.我相信您只需要 1 个工厂 class 即可容纳您的所有产品。 You can make a HashMap for every type of drink, but that makes it so you always have to update your factory class when you make a new type of drink.您可以为每种类型的饮料制作 HashMap,但这使得您在制作新型饮料时始终必须更新您的工厂 class。 What you can do is make a single HashMap with as key Product and as value Integer and then save your enum of the type of drink in the Product class.您可以做的是制作一个 HashMap 作为关键Product和作为值Integer ,然后将您的饮料类型的枚举保存在Product class 中。 The reason is because the type of drink is a property of a product.原因是饮料的类型是产品的属性。 Now the only way to tell the type of drink is by knowing in what HashMap it is saved in. That seems inefficient considering later in your code you might have access to a Product instance, without having access to the HashMap in your factory.现在判断饮料类型的唯一方法是知道它保存在什么 HashMap 中。考虑到稍后在您的代码中您可能可以访问 Product 实例,而无法访问工厂中的 HashMap,这似乎效率低下。 When saving the type of drink in the Product instance itself, you can make a method that returns the type of drink and that's it.在 Product 实例本身中保存饮料类型时,您可以创建一个返回饮料类型的方法,仅此而已。

Question 3问题 3

"Is a CAST: beer.put((Alchogol) product,amount); normal way?" “是 CAST: beer.put((Alchogol) product,amount); 正常方式吗?”

Whether this is ok or not really depends on what you did beforehand.这是否可以,实际上取决于您事先做了什么。 This all has to do with the "A dog is an animal, but an animal is not always a dog" story.这一切都与“狗是动物,但动物并不总是狗”的故事有关。

Let's say you have an abstract class Animal and two classes Dog and Cat that both inherit from the Animal class.假设您有一个抽象的 class Animal和两个类DogCat ,它们都继承自Animal class。 If you have an instance of an Animal inherited class that you want to cast to Dog and you did not check before if this instance is actually a dog, you are asking for errors to be thrown.如果您有一个Animal的实例继承了 class 并且您想要强制转换为Dog并且您之前没有检查此实例是否实际上是一只狗,那么您要求抛出错误。 The instance could be an instance of a Dog class, but it could also be an instance of a Cat class.该实例可以Dog class 的实例,但也可以是Cat class 的实例。 If you try to cast it and you are casting it to the wrong inherited type, you will get a java.lang.ClassCastException .如果您尝试将其转换为错误的继承类型,您将得到java.lang.ClassCastException

To solve the probable situation where this error could be thrown, always check beforehand if the variable you are trying to cast is of a specific inherited type.要解决可能引发此错误的可能情况,请务必事先检查您尝试转换的变量是否属于特定的继承类型。 You should have a look at theinstanceof keyword.你应该看看instanceof关键字。

FYI, modern IDEs will most of the time give you a warning when you try to cast a variable if you did not check it beforehand.仅供参考,如果您没有事先检查变量,现代 IDE 在大多数情况下会在您尝试强制转换变量时向您发出警告。


My main language is not English.我的主要语言不是英语。 I tried to explain it the best I could.我尽力解释它。 If you do have comments or anything that you would like to let me know, feel free to edit my comment or put a comment under it.如果您确实有任何意见或任何想让我知道的内容,请随时编辑我的评论或在其下方发表评论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM