Методы выставления нескольких Интерфейсов (через статические методы создания) - PullRequest
4 голосов
/ 30 августа 2011

В настоящее время я работаю над проектом, в котором пытаюсь скрыть как можно больше подробностей об иерархии, которую я создал.Я хочу сделать это, чтобы минимизировать объем информации, которую пользователь должен знать об объектах (и контролировать, что они могут делать с состоянием объекта).Кроме того, я использую этот шаблон, чтобы ограничить типы объектов, которые может создавать приложение, и ограничить его созданием на заводе.

Однако основная проблема, с которой я сталкиваюсь, заключается в том, что существует несколькоразные виды интерфейсов я бы хотел выставить.Каждый интерфейс имеет дополнительную функциональность, которую я не считаю общей, и я хотел бы разделить эти интерфейсы.Наконец, я не знаю, какие новые интерфейсы могут появиться в будущем, но я хотел бы попробовать и быть готовым к ним.

Weapon:

public interface Weapon extends GameObject {
    Number attack();

    boolean addWeaponAttribute(WeaponAttribute attribute);
}

Firearm:

public interface Firearm extends Weapon {
    void reload(Number rounds);
}

Мой вопрос: каков наилучший способ заставить фабрику производить объекты с различными интерфейсами?Вот что я считаю «лучшим будет»:

  1. Наиболее понятным для пользователя (очевидно, о чем они просят и что получают)
  2. Лучшее для будущего расширения (я не уверен, какие новые интерфейсы я добавлю к этой системе).

Вот что я думал до сих пор:

Создание правильно названных методов длякаждый интерфейс

public static Firearm getFirearm(String firearmName) {
    ...
}

public static Weapon getWeapon(String weaponName) {
    ...
}

Делайте выше, но производите фабрики в отдельно названных классах

public class WeaponFactory {
    public static Weapon getWeapon(String weaponName) {
        ...
    }
}


public class FirearmFactory {    
    public static Firearm getFirearm(String firearmName) {
        ...
    }
}

Что-то совершенно другое

Я открыт для предложений и изменений,Это гибкий проект, поэтому я могу изменить столько, сколько захочу (с точки зрения этой части проекта), чтобы добиться лучшего результата.

Кроме того - Как примечание, я не был уверен, что этовопрос был слишком открытым или нет для SO.Если я ошибся, разместив здесь сообщение, дайте мне знать, и я перенесу свой вопрос в другое место.

Ответы [ 4 ]

2 голосов
/ 30 августа 2011

Что я могу предложить, это сделать интерфейсы как можно более краткими и переместить другие несвязанные методы в другое место. Вы могли бы рассмотреть возможность сделать это, например:

public interface Weapon extends GameObject {
    Number attack();
}

public interface Modifiable extends GameObject {
    boolean addWeaponAttribute(WeaponAttribute attribute);
}

public class ActualWeapon implements Weapon, Modifiable {
...
}

Затем вы можете создавать различные фабрики для создания ваших конкретных объектов, как вы уже упоминали:

public class WeaponFactory {
    public static Weapon getWeapon(String weaponName) {
        ...
    }
}

или

public class GenericFactory<T extends GameObject> {
    public T createGameObject(Object... properties) {
        ...
    }
}
public class WeaponFactory extends GenericFactory<ActualWeapon> {
    public ActualWeapon createGameObject(Object... properties) {
        ...
    }
}

Я думаю, вы не можете добавлять статические методы к интерфейсам. Я бы не советовал, если бы вы могли.

1 голос
/ 30 августа 2011

возможно, просто используйте шаблон проектирования фабричного метода, например

interface GameObject {}
class WeaponAttribute {}
interface Weapon extends GameObject {
    Number attack();
    boolean addWeaponAttribute(WeaponAttribute attribute);
}
interface Firearm extends Weapon {
    void reload(Number rounds);
}
class WeaponBaseClass implements Weapon {
    WeaponBaseClass(WeaponName weaponName) {
        this.weaponName=weaponName;
    }
    @Override public Number attack() {
        return null;
    }
    @Override public boolean addWeaponAttribute(WeaponAttribute attribute) {
        return false;
    }
    public String toString() {
        return weaponName.toString();
    }
    final WeaponName weaponName;
}
class FirearmBaseClass extends WeaponBaseClass implements Firearm {
    public FirearmBaseClass(WeaponName weaponName) {
        super(weaponName);
    }
    @Override public void reload(Number rounds) {}
}
enum WeaponName {
    knife, sword, colt45, glock19, glock19WithLaser;
}
class WeaponCreator {
    Weapon create(WeaponName weaponName) {
        switch (weaponName) {
            case knife:
            case sword:
                return new WeaponBaseClass(weaponName);
            case colt45:
            case glock19:
                return new FirearmBaseClass(weaponName);
            default:
                return new WeaponBaseClass(weaponName);
        }
    }
}
class FancyWeaponCreator extends WeaponCreator {
    Weapon create(WeaponName weaponName) {
        Weapon weapon = null;
        switch (weaponName) {
            case glock19WithLaser:
                weapon = super.create(WeaponName.glock19);
                // whatever it needs
                return weapon;
            default:
                return new WeaponBaseClass(weaponName);
        }
    }
}
public class Main {
    public static void main(String[] args) {
        System.out.println(new WeaponCreator().create(WeaponName.knife));
        System.out.println(new WeaponCreator().create(WeaponName.colt45));
        System.out.println(new FancyWeaponCreator().create(WeaponName.glock19WithLaser));
    }
}
1 голос
/ 30 августа 2011

При использовании дженериков вам может понадобиться только один фабричный метод, например:

public <T> T getObject(java.lang.Class<T> responseType, String name)

Тогда пользователь будет звонить:

Weapon weapon = factory.getObject(Weapon.class, "my weapon");
1 голос
/ 30 августа 2011

А как насчет фабрики фабрик?Каждая фабрика будет реализовывать свою фабрику.Ifacorty потребует метод Instantiate (строковый тип) и вернет ваш экземпляр оружия с подклассами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...