что такое класс без гражданства? - PullRequest
1 голос
/ 05 октября 2011

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

Ответы [ 6 ]

4 голосов
/ 20 октября 2016

Вот пример из реального мира: Написание плагинов для Microsoft Dynamics CRM .

В этом документе вы увидите заметку с надписью: «Метод Execute плагина должен быть написан так, чтобы он не имел состояния». И, в сущности, это означает, что быть классом без состояния является то, что не должно быть глобальных переменных (за исключением нескольких особых случаев, в которые я не буду входить, если их не спросить).

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

Основная нить:

YourCustomPlugin yourCustomPluginCached = new YourCustomPlugin();

затем позже: Резьба1:

yourCustomPluginCached.Execute(context1);

и Тема 2:

yourCustomPluginCached.Execute(context2);

То, что некоторые разработчики делают неправильно, они создают глобальную переменную для хранения контекста, которую они устанавливают в качестве первой строки в методе Execute (). Таким образом, они не должны передавать это между всеми своими методами. Но это на самом деле огромная ошибка. Потому что, если они это делают, и в сценарии выше, если выполнение в thread2 начинается до завершения выполнения из thread1. Это будет означать, что context1 в thread1 будет перезаписан context2. И теперь этот плагин будет иметь неожиданный результат. В 99% случаев, даже при неправильной разработке, проблем нет или нет заметных проблем. Но в 1% случаев это приведет к тому, что что-то пойдет не так, и что разработчику будет невероятно трудно понять, что пошло не так, и, вероятно, никогда не произойдет, когда он будет тестировать / отлаживать. Так что он, вероятно, останется незафиксированным долгое время.

1 голос
/ 05 октября 2011

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

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

Единственная причина, по которой я могу придумать создание такого объекта без состояния, заключается в том, что вы хотите, чтобы реальная функциональность определялась во время выполнения. Таким образом, если у вас есть класс UtilsBase, который предлагает набор виртуальных методов, и UtilsDerived, который переопределяет некоторые из методов, вы можете передать любому, кому нужно использовать utils, ссылку на UtilsBase и создать фактические утилиты объект во время выполнения, в соответствии с конкретными потребностями.

1 голос
/ 05 октября 2011

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

1 голос
/ 05 октября 2011

Если под классом без сохранения состояния вы подразумеваете класс неизменяемых объектов, то недостатком является то, что операции мутирования должны копировать объект, а не менять его на месте.Это может быть дорого.

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

0 голосов
/ 26 апреля 2018

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

Рассмотрим следующий фрагмент кода (игнорировать стандарты) -

class Maths {
int radius;

public void setRadius(int r) {
    this.radius = r;
}

public float getCircleArea() {
    return (float) (3.14 * radius * radius);
}
}

public class Geometry {
public static void main(String[] args) {
    Maths m = new Maths();
    m.setRadius(14);
    System.out.println(m.getCircleArea());
}
}

, если какой-либо другой работающий поток изменяет значение радиуса в классе Maths, тогда getCircleArea () даст нам другие результаты, потому чтосостояние переменной 'radius' может быть изменено, поскольку она является глобальной переменной.Эта проблема возникает в основном в веб-приложении, где мы используем бобовые контейнеры.Большинство бобов синглтон и имеет только одну копию.Если мы используем глобальные переменные, существует вероятность того, что значение глобальной переменной изменится.

Чтобы создать класс без состояния, попробуйте использовать локальную переменную, чтобы область действия переменной была ограничена.Примером вышеупомянутого getCircleArea () будет.

public float getCircleArea(int radius) {
    return (float) (3.14 * radius * radius);
}
0 голосов
/ 06 апреля 2015

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

public readonly class MyReadonlyClass
{
    public readonly double X {get;set;}
    public readonly double Y {get;set;}
    public readonly double Z {get;set;}

    public MyReadonlyClass(double x_,double y_,double z_)
    {
        X=x_;Y=y_;Z=z_;
    }
}

public readonly static class MyStaticReadonlyClass
{
    public readonly static double X {get;set;}
    public readonly static double Y {get;set;}
    public readonly static double Z {get;set;}

    static MyStaticReadonlyClass(double x_,double y_,double z_)
    {
        X=x_;Y=y_;Z=z_;
    }

}
...