Подходящий дизайн с использованием Generics с Wildcard - PullRequest
1 голос
/ 13 марта 2012

Я пытаюсь определить, смогут ли дженерики помочь мне в разработке лучшего и масштабируемого решения.В моем приложении есть класс модели, который отвечает за загрузку данных из источников данных, и я использую класс ModelProxy для предоставления некоторых методов из класса Model.

public interface ModelProxy {
     public int getOrderCount();
     public int getCustomerCount();
}

public abstract class AbstractModel {
     public abstract ModelProxy loadData(Configuration configuration);
}

public class ConcreteModel extends AbstractModel {
    public ModelProxy loadData(Configuration configuration) {
         loadInternal();
         return new ConcereteModelProxy(this);
    }
}

Пока все выглядит хорошо,но я смотрю, чтобы увидеть, могут ли дженерики (с подстановочными знаками) помочь мне разработать лучшее решение, которое позволило бы расширить интерфейс ModelProxy или класс Configuration.Например, в другом классе "Конкретная модель" я хотел бы использовать класс ExtendedConfiguration и ExtendedModelProxy.

public ExtendedModelProxy extends ModelProxy {
   // Additional methods
   public int getTotalCount();
}

public class ConcereteModel2 extends AbstractModel {
   public ExtendedModelProxy loadDate(ExtendedConfiguration configuration) {
      return new ConcreteExtendedModelProxy(this);
   }
}

Поможет ли Java Generics что-то подобное выше?Или, может быть, мой дизайн имеет недостатки, что мне нужно изменить его дизайн.Любые предложения будут очень полезны.

Спасибо,

Пример кода клиента:

public abstract class Service {
   public ModelProxy load(Configuration configuration) {
       return getModel().loadData(configuration);
   }

   protected abstract AbstractModel getModel();
}

public class ServiceImpl extends Service {
   protected AbstractModel getModel() {
      return new ConcreteModel();
   }

   public static void main() {
      Service service = new ServiceImpl();
      ModelProxy proxy = service.load(configuration);
      System.out.println(proxy.getOrderCount());
   }
}

public class ExtendedServiceImpl extends Service {
   protected AbstractModel getModel() {
      return new ConcreteModel2();
   }

   public static void main() {
      Service service = new ExtendedServiceImpl();
      ExtendedModelProxy proxy = (ExtendedModelProxy) service.load(configuration);
      System.out.println(proxy.getTotalCount());
   }
}

Надеюсь, я не слишком запутался.В ExtendedServiceImpl вы можете видеть, что мне нужно привести ModelProxy к ExtendedModelProxy, чтобы получить доступ к методу getTotalCount.Я думал, что, может быть, я смогу использовать дженерики, чтобы избежать бросков.Что-то вроде

public abstract <M extends ModelProxy, C extends Configuration> M loadData(C configuration);

Может быть, я слишком усложняю вещи, и действительно мой текущий дизайн - это все, что мне нужно.Не уверен ...

1 Ответ

0 голосов
/ 04 мая 2012

Как насчет такого рода вещей

package jj;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.*;

interface Configuration {
}

interface Model {
}

interface OrderModel extends Model {
    public int getOrderCount();
    public int getCustomerCount();
}

interface CustomerModel extends Model {
    public int getName();
    public int getAddress();
}

abstract class AbstractModel<M extends Model> {
    @SuppressWarnings("unchecked")
    public M loadData(Configuration configuration) {
        // connect to stuff
        Object connection = null;
        loadInternal(configuration, connection);
        // do some other stuff
        return (M) Proxy.newProxyInstance(null, new Class<?>[]{getModelClass()}, null);
    }

    protected abstract void loadInternal(Configuration configuration,
            Object connection);

    protected abstract InvocationHandler getInvocationHandler(Object connection);
    protected abstract Class<M> getModelClass();
}

class ConcreteOrderModel extends AbstractModel<OrderModel> {
    public void loadInternal(Configuration configuration,
            Object connection) {
    }

    protected InvocationHandler getInvocationHandler(Object connection) {
        return null;
    }

    protected Class<OrderModel> getModelClass() {
        return OrderModel.class;
    }
}

class ConcreteCustomerModel extends AbstractModel<CustomerModel> {
    public void loadInternal(Configuration configuration,
            Object connection) {
    }

    protected InvocationHandler getInvocationHandler(Object connection) {
        return null;
    }

    protected Class<CustomerModel> getModelClass() {
        return CustomerModel.class;
    }
}
...