我对Java很陌生。我正在尝试构建一个简单的类层次结构。
abstract class Vegetable
{
public Vegetable(double weight)
{
this.weight = weight;
...
}
...
}
class Tomato extends Vegetable
{
public Tomato(double weight)
{
super(weight);
...
}
...
}
class Cucumber extends Vegetable
{
public Cucumber(double weight)
{
super(weight);
...
}
...
}我在类Vegetable中有一些抽象方法,它们在Tomato和Cucumber中被重写。我想实施买蔬菜的逻辑。我为它创建了以下类:
public class VegetableFactory
{
public static ArrayList<Vegetable> buy(int num, Class vegetableClass)
{
ArrayList<Vegetable> res = new ArrayList<Vegetable>(num);
for (int i = 0; i < num; i++)
{
double weight = (Math.random() * 200) + 100;
Vegetable v = null;
try
{
v = (Vegetable) vegetableClass.getDeclaredConstructor(Double.TYPE).newInstance(weight);
} catch (InstantiationException e)
{
e.printStackTrace();
} catch (IllegalAccessException e)
{
e.printStackTrace();
} catch (InvocationTargetException e)
{
e.printStackTrace();
} catch (NoSuchMethodException e)
{
e.printStackTrace();
}
res.add(v);
}
return res;
}
} 这样做好吗?把它命名为工厂在意识形态上是正确的吗?任何改进建议都将受到高度赞赏。
发布于 2012-01-31 01:07:32
我会使用枚举类型,而不是必须传递一个类。这样,就不可能传递一些不好的内容,而且您可以在编译时而不是运行时捕获错误。
enum VegetableType { CARROT, TOMATO, CUCUMBER };那么你的购买方法就会很简单
static ArrayList<Vegetable> buy(int num, VegetableType vegType) {
ArrayList<Vegetable> veggies = new ArrayList<Vegetable>(n); //n is the initial capacity - size is still zero.
for(int i=0; i < num; ++i) {
double weight = (Math.random() * 200) + 100;
switch(vegType) {
case VegetableType.CARROT:
veggies.add(new Carrot(weight));
break;
case VegetableType.TOMATO:
veggies.add(new Tomato(weight));
break;
case VegetableType.CUCMBER:
veggies.add(new Cucumber(weight));
break;
}
}
return veggies;
}当然,现在的问题是在循环的中间有一个大的switch语句。一般来说,虽然很难看,但我认为这就足够了--您可以对每个单独的构造函数进行更多的控制,因此您不会被限制在相同的参数集上。
您可以做的另一件事是在VegetableType上使用一个工厂方法来创建一个实例:
enum VegetableType {
CARROT { Vegetable createInstance(int weight) { return new Carrot(weight); }},
TOMATO { Vegetable createInstance(int weight) { return new Tomato(weight); } },
CUCUMBER { Vegetable createInstance(int weight) { return new Cucumber(weight); } };
abstract Vegetable createInstance(int weight);
}然后你的名单就变成
static ArrayList<Vegetable> buy(int num, VegetableType vegType) {
ArrayList<Vegetable> veggies = new ArrayList<Vegetable>();
for(int i=0; i < num; ++i) {
double weight = (Math.random() * 200) + 100;
veggies.add(vegType.createInstance(weight));
}
return veggies;
} 最后,如果您想变得更漂亮,java.lang.reflect有Constructor类:
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/reflect/Constructor.html
然后,您可以使用它将构造函数获取到您选择的Vegetable类型,然后在循环中反复调用构造。
发布于 2012-01-31 04:46:34
这样做好吗?
不是的。对每个类的关注点分离给予更多的思考。购买逻辑不属于工厂。工厂只用于创建各种素食类型。Buy应该在VegetableStand类中,或者可能在Vegetable类中。
如果“购买”逻辑在每个蔬菜中都是唯一的,那么将buy()放在Vegetable类中--特别是如果它还具有一个price属性。即使如此,我仍然可以看到一个VegetableCart.Buy(),它将所有的东西积累到一个“袋子”中,这样就可以添加不同的蔬菜、数量和价格--给客户一个总价。
把它命名为工厂在意识形态上是正确的吗?
不是你写的那样。素食工厂是用来制造各种蔬菜的。我希望看到一个create()方法,如上面所建议的那样传递一个枚举。
public class VegetableStand {
VeggieFactory myVF = new VeggieFactory();
public ArrayList<Vegetable> bag = new ArrayList<Vegetable>;
public ArrayList<Vegetable> Buy (VegetableType whatKind ,int howMany){
for (int i=0, i<howMany; i++) {
bag.add(myVF.Create(whatKind);
}
}
public double TotalSale (ArrayList<Vegetable> bag) {
double totalPrice = new double;
foreach (Vegetable item in Bag) {
totalPrice += item.Price;
}
return totalPrice;
}
}
internal class VeggieFactory {
public static Vegetable Create(VegetableType whatKind) {
Vegetable thisKind;
switch(whatKind) {
case: VegetableType.carrot
thisKind = CreateCarrot();
break;
case: VegetableType.cucumber
thisKind = CreateCucumber();
break;
default:
throw new Veggie not invented yet exception;
}
return thisKind;
}
}然后,在buy()方法中,在for循环中不应该有一个大的switch语句。如果你通过一个素食主义的例子,这是没有道理的。如果你已经创造了那个素食主义者,那为什么是工厂?
ArrayList<Vegetable>的创建与蔬菜本身的创建分开。buy()方法为您购买的每一个蔬菜创建一个新列表。而且,您可能需要实例化一个素食者w/o列表。发布于 2012-01-31 12:17:35
据我所见,还没有人指出列表的引用类型应该仅为List。而不是
ArrayList<Vegetable> res = new ArrayList<Vegetable>(num);使用
List<Vegetable> res = new ArrayList<Vegetable>(num);该方法的签字也应改变:
public static List<Vegetable> buy(int num, Class vegetableClass)https://codereview.stackexchange.com/questions/8467
复制相似问题