Полное выравнивание с заменой Java Graphics.drawString?

Как отмечено в комментариях, ваш код завершается ошибкой, потому что для контейнера внедрения зависимостей ваша фабрика является допустимым источником для экземпляра IFoo. Таким образом, при запросе разрешения всех служб IFoo фабрика будет также запрашивать его.

Если вы хотите, чтобы это работало, вам придется каким-то образом разделить типы. Например, вы можете создать интерфейс маркера IActualFoo, который вы будете использовать вместо регистрации своих сервисов:

services.AddTransient<IActualFoo, Foo1>()
services.AddTransient<IActualFoo, Foo2>();

Внутри вашей IFoo фабрики вы можете затем разрешить IActualFoo и привести их к IFoo. Конечно, это означает, что IActualFoo будет наследоваться от IFoo и что ваши Foo службы действительно должны реализовать IActualFoo.


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

Было бы лучше, если бы фабрика могла принять решение о выборе правильной IFoo реализации. Обычно это выглядит так:

services.AddTransient<Foo1>();
services.AddTransient<Foo2>();
services.AddTransient<IFoo>(sp =>
{
    if (someMagicCondition)
        return sp.GetService<Foo1>();
    else
        return sp.GetService<Foo2>();
});

Таким образом, фабрика создаст правильный экземпляр в зависимости от некоторой логики условий. Хотя этот подход часто используется, он требует полной ответственности на заводе и ограниченного набора возможных IFoo реализаций во время разработки. Так что это не сработает, если вы хотите динамически добавлять реализации позже.

То, что вы также можете сделать, это зарегистрировать набор IFoo фабрик . Поэтому вместо того, чтобы реализация IFoo решала, является ли она правильной реализацией, перенесите эту логику на фабрику для каждой IFoo реализации:

services.AddSingleton<IFooFactory, Foo1Factory>();
services.AddSingleton<IFooFactory, Foo2Factory>();
services.AddSingleton<IFoo>(sp =>
{
    var factories = sp.GetServices<IFooFactory>();
    return factories.FirstOrDefault(f => f.CanFoo())?.CreateFoo();
});
public interface IFooFactory
{
    bool CanFoo();
    IFoo CreateFoo();
}

public Foo1Factory : IFooFactory
{
    public bool CanFoo() => true;
    public IFoo CreateFoo() => new Foo1();
}
public Foo2Factory : IFooFactory
{
    public bool CanFoo() => false;
    public IFoo CreateFoo() => new Foo2();
}

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

6
задан David Koelle 30 December 2008 в 15:38
поделиться

2 ответа

Хотя не самое изящное ни надежное решение, вот метод, который возьмет Font из тока Graphics возразите и получите FontMetrics для обнаружения, где нарисовать текст, и при необходимости, переместитесь в новую строку:

public void drawString(Graphics g, String s, int x, int y, int width)
{
    // FontMetrics gives us information about the width,
    // height, etc. of the current Graphics object's Font.
    FontMetrics fm = g.getFontMetrics();

    int lineHeight = fm.getHeight();

    int curX = x;
    int curY = y;

    String[] words = s.split(" ");

    for (String word : words)
    {
        // Find out thw width of the word.
        int wordWidth = fm.stringWidth(word + " ");

        // If text exceeds the width, then move to next line.
        if (curX + wordWidth >= x + width)
        {
            curY += lineHeight;
            curX = x;
        }

        g.drawString(word, curX, curY);

        // Move over to the right for next word.
        curX += wordWidth;
    }
}

Эта реализация разделит данный String в массив String при помощи split метод с пробелом как единственный разделитель слов, таким образом, это, вероятно, не очень устойчиво. Это также предполагает, что слово сопровождается пробелом и действует соответственно при перемещении curX положение.

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

17
ответ дан 8 December 2019 в 13:03
поделиться

Для перехода на новую строку Вам могло бы быть интересно тем, Как произвести Строку на нескольких строках с помощью Графики. Никакое выравнивание здесь, не уверенный, если это легко (или невозможно!) для добавления...

1
ответ дан 8 December 2019 в 13:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: