如何定义或引用将在视图中使用的模型类的属性

时间:2012-11-08 06:18:37

标签: java oop model-view-controller

我想让开发人员必须定义要在视图中显示的“模型”类的属性。

我曾想过使用枚举作为解决方案,但我认为不可能在超类(接口)中定义枚举。

如果我的描述不清楚,我很抱歉。这有点难以解释。我会尝试用特定的案例来解释。

Animal.java

public interface Animal {
    public void eat();
}

Bird.java

public class Bird implements Animal
{
    private String name;
    private int age;
    private Beak beak;
    private Wings wings;

    public Bird(String name, int age, Beak beak, Wings wings)
    {
        this.name = name;
        this.age = age;
        this.beak = beak;
        this.wings = organ;
    }

    //getter setter..

    @Override
    public void eat() {
        //eating
    }
}

Snake.java

public class Snake implements Animal
{
    private String name;
    private int age;
    private Fang fangs;

    public Snake(String name, int age, Fang fangs)
    {
        this.name = name;
        this.age = age;
        this.fangs = fangs;
    }

    //getter setter..

    @Override
    public void eat() {
        //eating
    }
}

Zoo.java

public class Zoo 
{
    private ArrayList<Bird> birds = new ArrayList<Bird>();
    private ArrayList<Snake> snakes = new ArrayList<Snake>();
    private ArrayList<Object?> birdsShownFeatures = new ArrayList<Object?>();
    private ArrayList<Object?> snakesShownFeatures = new ArrayList<Object?>();

    public Zoo()
    {
        birds.add(new Bird("Vulture", 2, new CrookedBeak(), new WideWing()));
        birds.add(new Bird("Whatever", 3, new WhateverBeak(), new WhateverWing()));
        birds.add(new Bird("Wut", 4, new WutBeak(), new WutWing()));

        snakes.add(new Snake("Cobra", 5, new TwinFang()));
        snakes.add(new Snake("Whatever", 5, new WhateverFang()));
        snakes.add(new Snake("Wut", 5, new WutFang()));

        birdsShownFeatures.add(new Object?("name"));
        birdsShownFeatures.add(new Object?("beak"));
        birdsShownFeatures.add(new Object?("wings"));

        snakesShownFeatures.add(new Object?("name"));
        snakesShownFeatures.add(new Object?("fangs"));
    }

    public void showOff()
    {
        for(Bird bird:birds)
        {
            for(Object? object:birdsShownFeatures)
            {
                System.out.println("Bird: "+bird.unknownFunction(object));
            }
        }

        for(Snake snake:snakes)
        {
            for(Object? object:snakesShownFeatures)
            {
                System.out.println("Snake: "+snake.unknownFunction(object));
            }
        }
    }
}

我必须概括Animal(Object?)的子类的属性。我必须能够定义一个函数来检索该属性(unknownFunction)。

换句话说,我希望能够轻松定义动物子类的某些属性,并且能够相应地进行处理。

完美(不真实?)示例:

public class Zoo {
    private ArrayList<Bird> birds = new ArrayList<Bird>();
    private ArrayList<Snake> snakes = new ArrayList<Snake>();
    private ArrayList<Object> birdsShownFeatures = new ArrayList<Object>();
    private ArrayList<Object> snakesShownFeatures = new ArrayList<Object>();

    public Zoo()
    {
        birds.add(new Bird("Vulture", 2, new CrookedBeak(), new WideWing()));
        birds.add(new Bird("Whatever", 3, new WhateverBeak(), new WhateverWing()));
        birds.add(new Bird("Wut", 4, new WutBeak(), new WutWing()));

        snakes.add(new Snake("Cobra", 5, new TwinFang()));
        snakes.add(new Snake("Whatever", 5, new WhateverFang()));
        snakes.add(new Snake("Wut", 5, new WutFang()));

        birdsShownFeatures.add(Bird.NAME);
        birdsShownFeatures.add(Bird.BEAK);
        birdsShownFeatures.add(Bird.WINGS);

        snakesShownFeatures.add(Snake.NAME);
        snakesShownFeatures.add(Snake.FANGS);
    }

    public void showOff()
    {
        for(Bird bird:birds)
        {
            for(Object object:birdsShownFeatures)
            {
                System.out.println("Bird: "+bird.get(object));
            }
        }

        for(Snake snake:snakes)
        {
            for(Object object:snakesShownFeatures)
            {
                System.out.println("Snake: "+snake.get(object));
            }
        }
    }
}

枚举无法正常工作,因为我无法 FORCE 开发人员在每次创建实现Animal的类时都会进行实现接口的特定枚举。

蛇和鸟属性必须能够一般化。但仍然定义。使每个属性实现一个特定的接口都不是一个选择,因为在所有需要的类(包括本机)实现一个接口的过程中会很痛苦。

很抱歉,如果它太混乱了。我不知道如何正确解释这个案子。

1 个答案:

答案 0 :(得分:0)

您可以使用反射和泛型。这是对你问题的回答,但我认为这是一个糟糕的选择。

使用您的表示例(请参阅注释)我会使用类似通用Table<T>的方法,并使用getRow()方法返回一行(对于Bird"Vulture", 2, "CrookedBeak", "WideWing"),如果最终的开发者想要一个不同的行,他可以覆盖你的getRow到别的东西。 另一种选择是在表构造函数中接受Function<T, Row>(参见google guava functions


快速&amp;脏样本泛型和反射代码示例:

AbstractAnimal

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

public abstract class AbstractAnimal<T extends Enum<T>> {
    private List<T> selectedFields = new ArrayList<T>();

    public AbstractAnimal(Class<T> clazz)
    {
        if (clazz != null) {
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (Modifier.isStatic(field.getModifiers()) && 
                    Modifier.isPublic(field.getModifiers())) {
                    this.selectedFields.add(Enum.valueOf(clazz, field.getName()));
                }
            }
        }
    }

    public abstract void eat();

    public List<T> getSelectedFields()
    {
        return this.selectedFields;
    }

    public Object get(T name)
    {
        if (name == null) {
            return null; 
        }

        try {
            final Class<?> clazz = this.getClass();
            final Field declaredField = clazz.getDeclaredField(name.name().toLowerCase());
            if (declaredField != null) {
                declaredField.setAccessible(true);
                return declaredField.get(this);
            }
        } catch (IllegalAccessException ex) {
            // ignore
        } catch (NoSuchFieldException e) {
            // ignore
        } catch (SecurityException e) {
            // ignore
        }
        return null;
    }
}

public class Bird extends AbstractAnimal<Bird.Fields> {

    public static enum Fields {
        NAME, AGE, BEAK, WINGS
    }

    private String name;

    private int age;

    private String beak;

    private String wings;

    public Bird(String name, int age, String beak, String wings)
    {
        super(Fields.class);
        this.name = name;
        this.age = age;
        this.beak = beak;
        this.wings = wings;
    }

    // getter setter..

    @Override
    public void eat()
    {
        // eating
    }
}

动物园

package com.foo;

import java.util.ArrayList;

public class Zoo {
    private ArrayList<Bird> birds = new ArrayList<Bird>();

    public Zoo()
    {
        birds.add(this.buildBird("Vulture", 2, "CrookedBeak", "WideWing"));
        birds.add(this.buildBird("Whatever", 3, "WhateverBeak", "WhateverWing"));
        birds.add(this.buildBird("Wut", 4, "WutBeak", "WutWing"));
    }

    public void showOff()
    {
        for(Bird bird:birds)
        {
            for (final Bird.Fields selectedField : bird.getSelectedFields()) {
                System.out.println("bird: " + bird.get(selectedField));
            }
        }
    }

    private Bird buildBird(String name, int age, String beak, String wings) 
    {
        Bird result = new Bird(name, age, beak, wings);
        result.getSelectedFields().remove(Bird.Fields.AGE);
        return result;
    }

    public static void main(final String[] args) {
        Zoo z = new Zoo();
        z.showOff();
    }
}

输出

bird: Vulture
bird: CrookedBeak
bird: WideWing
bird: Whatever
bird: WhateverBeak
bird: WhateverWing
bird: Wut
bird: WutBeak
bird: WutWing