Как расширить этот дизайн для универсального конвертера в Java? - PullRequest
4 голосов
/ 08 июня 2010

Вот небольшой кусок конвертера валют:

 public enum CurrencyType {

        DOLLAR(1),
        POUND(1.2),
        RUPEE(.25);

        private CurrencyType(double factor) {
            this.factor = factor;
        }
        private double factor; 

        public double getFactor() {
            return factor;
        }

    }

    public class Currency {

        public Currency(double value, CurrencyType type) {
            this.value = value;
            this.type = type;
        }

        private CurrencyType type;
        private double value;

        public CurrencyType getCurrencyType() {
            return type;
        }

        public double getCurrencyValue() {
            return value;
        }

        public void setCurrenctyValue(double value){
            this.value = value;
        }

    }

public class CurrencyConversion {


    public static Currency convert(Currency c1, Currency c2)
            throws Exception {
        if (c1 != null && c2 != null) {
            c2.setCurrenctyValue(c1.getCurrencyValue()
                    * c1.getCurrencyType().getFactor()
                    * c2.getCurrencyType().getFactor());
            return c2;
        } else
            throw new Exception();
    }


}

Я хотел бы улучшить этот код, чтобы он работал для различных единиц преобразования, например: килограммы в фунты, мили в километры и т. Д. И т. Д. Что-то похожее на это:

public class ConversionManager<T extends Convertible> {


    public T convert(T c1, T c2) 
    {
        //return null;
    }
}

Ценю ваши идеи и предложения.

Ответы [ 3 ]

4 голосов
/ 08 июня 2010

На мой взгляд, это объектно-ориентированный способ сделать это. Обратите внимание, что вы также можете шаблонизировать тип данных, но я только что использовал здесь двойные числа, поскольку они могут представлять любые скалярные единицы. Это обеспечивает хороший способ обработки конверсии между единицами разных показателей, как вы просили: расстояние, валюта, масса и т. Д.

public interface Metric {
    public String getReferenceUnit();
}

public class Distance implements Metric {
    public String getReferenceUnit() {
        return new String("Meters");
    }
}

public interface Units<T extends Metric> {
    public double getToReferenceFactor();
}

public class Kilometers implements Units<Distance> {
    public double getToReferenceFactor() {
        return 1000;
    }
}

static <T extends Metric> double convert(Units<T> from, Units<T> to) {
    return from.getToReferenceFactor() * (1.0 / to.getToReferenceFactor());
}
1 голос
/ 08 июня 2010

Здесь представлен универсальный преобразователь, который использует полую матрицу и выполняет транзитивное замыкание для объединения известных преобразователей.В этом случае он преобразует единицы длины:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Converter {
    private static final Map<String, Map<String, Double>> FACTOR_MAP
            = new HashMap<String, Map<String, Double>>();

    public static double convert(String from, String to, double value) {
        List<Step> stack = new ArrayList<Step>();
        stack.add(new Step(from, value));
        while (!stack.isEmpty()) {
            Step s = stack.remove(0);
            double val = s.value;
            String source = s.unit;
            if (source.equals(to)) {
                return val;
            }
            Map<String, Double> map = FACTOR_MAP.get(source);
            if (map != null) {
                for (Map.Entry<String,Double> entry: map.entrySet()) {
                    stack.add(new Step(entry.getKey(), val*entry.getValue()));
                }
            }
        }
        throw new IllegalArgumentException("Cannot not convert from " + from
                + " to " + to);
    }

    public static void registerFactor(String from, String to, double factor) {
        putFactor(from, to, factor);
        putFactor(to, from, 1.0/factor);
    }

    private static void putFactor(String from, String to, double factor) {
        Map<String, Double> map = FACTOR_MAP.get(from);
        if (map == null) {
            map = new HashMap<String, Double>();
            FACTOR_MAP.put(from, map);
        }
        map.put(to, factor);
    }

    static {
        registerFactor("cm", "mm", 10);
        registerFactor("in", "cm", 2.54);
        registerFactor("in", "pt", 72);
        registerFactor("pc", "pt", 12);
        registerFactor("px", "mm", 0.28);
    }

    private static class Step {
        private String unit;
        private double value;

        Step(String unit, double value) {
            this.unit = unit;
            this.value = value;
        }
    }
}

Следующая программа:

public class Main {
    private static final String UNITS[] = {"cm", "mm", "in", "pt", "pc", "px"};

    public static void main(String[] args) {
        for (String unit1: UNITS) {
            for (String unit2: UNITS) {
                System.out.println("1" + unit1 + " = "
                        + Converter.convert(unit1, unit2, 1) + unit2);
            }
        }
    }
}

дает следующие результаты:

1cm = 1.0cm
1cm = 10.0mm
1cm = 0.39370078740157477in
1cm = 28.346456692913385pt
1cm = 2.3622047244094486pc
1cm = 35.71428571428571px
1mm = 0.1cm
1mm = 1.0mm
1mm = 0.03937007874015748in
1mm = 2.8346456692913384pt
1mm = 0.23622047244094485pc
1mm = 3.571428571428571px
1in = 2.54cm
1in = 25.4mm
1in = 1.0in
1in = 72.0pt
1in = 6.0pc
1in = 90.71428571428571px
1pt = 0.035277777777777776cm
1pt = 0.35277777777777775mm
1pt = 0.013888888888888888in
1pt = 1.0pt
1pt = 0.08333333333333333pc
1pt = 1.2599206349206347px
1pc = 0.42333333333333334cm
1pc = 4.233333333333333mm
1pc = 0.16666666666666666in
1pc = 12.0pt
1pc = 1.0pc
1pc = 15.119047619047619px
1px = 0.028000000000000004cm
1px = 0.28mm
1px = 0.011023622047244094in
1px = 0.7937007874015748pt
1px = 0.06614173228346457pc
1px = 1.0px
1 голос
/ 08 июня 2010

Перечисления в java, к сожалению, не поддерживают интерфейсы или суперклассы (я хотел бы выяснить причину этого).

Что вы можете сделать, это объявить аннотацию для ваших типов перечислений (например,, @Convertible) и получить доступ к его коэффициенту с помощью отражения.Это довольно уродливо, и вы не сможете использовать выражения «T extends Convertible» в обобщенных выражениях.

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