Pregunta

class PieceFactory {     
     @SuppressWarnings("rawtypes")
     public Piece createPiece(String pieceType) throws Throwable{
        Class pieceClass = Class.forName(pieceType);
        Piece piece = (Piece) pieceClass.newInstance();

         return piece;       
     }
}

No estoy todo usado para el manejo de excepciones, por tanto, sin embargo, sólo estoy tirarlos, pero en todas partes utilizo un método que utiliza esta fábrica me tengo que lanzar excepciones como throwable dice.

Por ejemplo, en una de mis clases tengo un método que crea la instancia de una gran cantidad de objetos utilizando el método que utiliza la fábrica. Puedo utilizar el método de esa clase con sólo tirar la excepción, sin embargo, no funcionará si trato de pasar una referencia a esa clase a otra clase y luego usar el método de allí. Entonces me obliga a intentar detectar la excepción.

Probablemente no necesita una fábrica, pero nos pareció interesante y me gustaría probar a los patrones de uso. La razón por la que creé la fábrica es que tengo 6 subclases de pieza y me wa no utilizar un método para crear instancias de ellos al pasar el tipo de subclase quiero como un argumento para el método.

¿Fue útil?

Solución

Está intentando crear un objeto reflexivamente Piece.

Class.forName() lanza ClassNotFoundException, mientras Class.newInstance() lanza InstantiationException, IllegalAccessException (de ahí por qué tiene que tirar Throwable.

Una mejor manera de crear un objeto a través de los tipos de clases es, probablemente, de la siguiente manera:

class PieceFactory {     

    public Piece createPiece(String pieceType) throws Throwable{
        Piece piece = null;

        if ("SubPiece1".equals(pieceType)) {
            piece = new SubPiece1();
        } else if ("SubPiece2".equals(pieceType)) {
            piece = new SubPiece2();
        }

        return piece;       
    }
}

PS , que es no probado, sólo mostrar una mejor manera de hacerlo.

Espero que esto ayude! :)

Otros consejos

Ambos @SuppressWarnings y throws Throwable campanas de alarma anillo. Ver Effective Java por Bloch.

Si usted no desea declarar lanza declaraciones o try / catch en todas partes.

Crea una clase y extender la clase RuntimeException o uso propio RuntimeException o RuntimeException relacionada extiende clases.

A continuación, el bloque try-catch lugar a la raíz (métodos de su clase de fábrica) y envolver las excepciones producidas en un tipo de excepción de tiempo de ejecución (uno de los anteriores, cualquiera que elija).

Sin embargo, lo que realmente depende de lo que necesita. En algún momento usted todavía tendrá que excepciones mango o la aplicación va a lanzar una excepción en tiempo de ejecución y aplicación no hará lo que se esperaba si no manejarlos.

try{ 
    "your code which throws exception" 
} catch(ThrownExceptionType e){ 
   throw new RuntimrException(e);
}

Recuerde que todavía tienen que manejar la excepción. Esto no significa que esto va a funcionar todo bien.

Las excepciones deben ser atrapados en alguna parte. Si he entendido correctamente que tiene una clase que se envuelve alrededor de esta fábrica, por ejemplo un FactoryWrapper. En algún lugar de su código se utiliza esa clase envoltorio y que son capaces de tirar cualquiera excepción o cogerlo porque el método en el que está utilizando es probable que esté rodeado en algún momento (en una clase base probablemente) por un bloque try / catch, mientras que el otro lugar (a la que usted está pasando su referencia FactoryWrapper) es probablemente el último recurso (que no es una práctica buena, pero podría ser un método que nunca se llama) donde la necesidad excepción a ser capturado.

Esto es sólo una posible explicación de por qué no se puede tirar la excepción en su otra clase. Como otros ya han mencionado, trate de no usar la reflexión, ya que es mucho más lento que las otras alternativas.

Se puede usar una fábrica abstracta y luego una fábrica para cada tipo. Ver detalles aquí y aquí . Espero que esto ayude.

EDIT:

Aquí es un interesante artículo sobre la reflexión. Se le dará una idea de cuándo usarlo.

Le recomiendo que trabaja en encontrar una posición cómoda con la escritura de controladores de excepciones. De lo contrario su única opción es enigma de su código con declaraciones throws dificultades que se convierte en molesto y causas, como hemos visto ya.

En este caso, el cuerpo de su método puede lanzar excepciones: dos comprobado. ClassNotFoundException de la llamada forname() y InstantiationException de la llamada newInstance()

Como mejor manejar estas depende de su aplicación y su preferencia. Como sugiere otra respuesta, una opción es simplemente atraparlos y lanzar excepciones sin marcar. Esto es razonable si se espera que estas excepciones no deberían ocurrir una vez que la solicitud está completa. Este es probablemente el enfoque me gustaría tener aquí, ya que si cualquiera de estas excepciones se produjo probablemente indicaría un error de configuración.

Pero si hay razones para pensar que estas excepciones podrían producirse razonable en el uso normal, usted debe pensar acerca de cómo desea para manejarlos. Por ejemplo, si el nombre de la pieza subclase se está introduciendo en una interfaz gráfica de usuario por un usuario (no es probable, lo sé, pero sólo para el punto), entonces se convierte en un ClassNotFoundException mucho más probable, ya que el nombre podría ser fácilmente mal escrito. En esa situación, podría tener sentido para permitir que este método de tirar esa excepción, y requieren de la persona que llama a la captura y manejar la situación (por ejemplo, proporcionando un respaldo mensaje al usuario que la clase solicitada no existe).

El uso de la reflexión como lo hace no es lo ideal. Tan pronto como cambia el nombre de una clase de unidades y de los clientes pasan Hardcoded totalmente calificados-nombres de las clases, su aplicación va a romper. La sugerencia de la Elite Gent evita ese problema, pero aún requiere que los clientes saber la clase concreta, que es exactamente lo que el patrón de la fábrica intentos de ocultar. Un enfoque mejor en mi opinión sería para cualquiera que use una enumeración para representar tipos de unidades y de dejar pasar el cliente que como argumento a su método de fábrica, o crear métodos de fábrica independientes para cada tipo (con 6 tipos de piezas que es factible).

Desde que estoy postergando todos modos, aquí un ejemplo de la enumeración-enfoque:

import java.util.ArrayList;
import java.util.List;

class PieceFactoryExample {

    static enum PieceFactory {
        ROOK {
            Piece create() {
                return new Rook();
            }
        };
        abstract Piece create();
    }

    static class Field {
        char line;
        int row;

        public Field(char line, int row) {
            this.line = line;
            this.row = row;
        }

        public String toString() {
            return "" + line + row;
        }
    }

    static interface Piece {

        void moveTo(Field field);

        List<Field> possibleMoves();
    }

    static abstract class AbstractPiece implements Piece {

        Field field;

        public void moveTo(Field field) {
            this.field = field;
        }
    }

    static class Rook extends AbstractPiece {

        public List<Field> possibleMoves() {

            List<Field> moves = new ArrayList<Field>();
            for (char line = 'a'; line <= 'h'; line++) {
                if (line != field.line) {
                    moves.add(new Field(line, field.row));
                }
            }
            for (char row = 1; row <= 8; row++) {
                if (row != field.row) {
                    moves.add(new Field(field.line, row));
                }
            }
            return moves;
        }
    }

    public static void main(String[] args) {

        Piece pawn = PieceFactory.ROOK.create();
        Field field = new Field('c', 3);
        pawn.moveTo(field);
        List<Field> moves = pawn.possibleMoves();
        System.out.println("Possible moves from " + field);
        for (Field move : moves) {
            System.out.println(move);
        }
    }
}

Me hizo todo lo estático aquí para mantener el ejemplo autónomo. Normalmente campo, Piece, AbstractPiece y la torre sería clases del modelo de nivel superior y PieceFactory sería de alto nivel también.

Esta es una mejor manera de ir por su ejemplo que pienso, y evita el problema de manejo de excepciones.

Volviendo a esto, hay un par de enfoques que puede considerar (basado en el enfoque de reflexión):

Lanzar Throwable igual que lo hizo es una mala práctica, ya que agrupa todos los errores y hace que el manejo de errores muy engorroso y poco transparente para los clientes. No hacer eso a menos que no tienen otras opciones.

declare 'lanza' en su método para todas las excepciones controladas. Para decidir si esto es válido, tenga en cuenta si el cliente debe conocer y entender el tipo de excepción que está lanzando. En su ejemplo, si el cliente que quiere crear una Torre conocer y comprender el InstantiationException, IllegalAccessException y ClassNotFoundException lanzada por su código de reflexión? Probablemente no en este caso.

envolverlos en una excepción en tiempo de ejecución, que no necesita ser capturado por los clientes. Esto no es siempre una buena idea. El hecho de que el código que está llamando es lanzar excepciones controladas por lo general tiene una razón. En el ejemplo que estaba haciendo la reflexión, y esto puede ir mal en muchos aspectos (la API declara LinkageError, ExceptionInInitializerError, ClassNotFoundException, IllegalAccessException, InstantiationException y SecurityException). Envolver las excepciones comprobadas en una excepción de ejecución no hace que el problema desaparezca. Considero que hacer esto un 'código de olor'. Si el error se refiere a un fallo del sistema irrecuperable, entonces podría ser una opción válida, pero en la mayoría de los casos que se quiere manejar este tipo de fallas con más gracia.

Lanza una excepción personalizada comprobado para un subsistema completo. Véase, por ejemplo org.springframework.dao.DataAccessException de primavera que se utiliza para envolver todas las excepciones de acceso a datos específicos de la aplicación. Esto significa clientes tendrán que coger un solo tipo de excepción y pueden averiguar los detalles si es necesario. En su caso se podría crear una marcada PieceCreationException y usar eso para envolver todos los errores de reflexión. Este es un patrón de manejo de excepción válida, pero creo que podría ser un poco que entregó pesado para su PieceFactory.

nula

Vuelta. Se puede coger todas las excepciones dentro de su código y simplemente devolver null si se producen. Sólo asegúrese de que su JavaDoc indica claramente esto. Un inconveniente de este enfoque es que los clientes podrían tener que comprobar si hay valores nulos en todas partes.

Vuelta un tipo de error específico. Este es un geek (muy orientado a objetos) enfoque que vi en el núcleo de la API de Java en algún lugar un tiempo atrás (maldito, no recuerdo dónde). Para ello, se crearía un tipo de pieza extra:

class NullPiece implements Piece {
    public void moveTo(Field field) {
        throw new UnsupportedOperationException("The Piece could not be created");
    }
    public List<Field> possibleMoves() {
        throw new UnsupportedOperationException("The Piece could not be created");
    }
}

y devolver una instancia de este tipo cuando se produce un error durante la creación. La ventaja es que es más auto-documentado de devolver una sencilla nulo valor, pero los clientes que, por supuesto, tiene que comprobar esto usando algo como instanceof. Si no lo hacen, entonces van a encontrarse con el UnsupportedOperationException produce cuando se llaman los métodos pieza. Un poco pesado, pero muy explícita. No estoy seguro de que iría tan lejos, pero sigue siendouna idea interesante.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top