Другая опция состоит в том, чтобы использовать битовые поля:
struct bits {
unsigned int a:1;
unsigned int b:1;
unsigned int c:1;
};
struct bits mybits;
определяет 3-разрядное поле (на самом деле, это - три 1-разрядных felds). Битовые операции теперь становятся немного (ха-ха) более простым:
, Чтобы установить или очиститься немного:
mybits.b = 1;
mybits.c = 0;
Для переключения немного:
mybits.a = !mybits.a;
mybits.b = ~mybits.b;
mybits.c ^= 1; /* all work */
Проверка немного:
if (mybits.c) //if mybits.c is non zero the next line below will execute
Это только работает с битовыми полями фиксированного размера. Иначе необходимо обратиться к методам битового жонглирования, описанным в предыдущих сообщениях.
Вы можете использовать отражение. Примерно так:
public interface Model {
class Singleton {
public static Model instance(Class<? extends Model> modelClass) {
try {
return (Model)modelClass.getField("instance").get(null);
} catch (blah-blah) {
blah-blah
}
}
}
public class XmlModel implements Model {
private static final Model instance = new XmlModel();
private XmlModel() {
}
}
использование:
Model.Singleton.instance(XmlModel.class)
На самом деле, мне этот код не очень нравится :). Во-первых, он использует отражение - очень медленное, во-вторых, возможны ошибки времени выполнения в случае неправильного определения классов.
Можете ли вы преобразовать интерфейс в абстрактный класс? Это позволит вам применить определенный фабричный метод ко всем реализующим классам.
public enum MyXMLModel{
INSTANCE();
//rest of class
};
EDIT: Другая возможность - создать классы делегатов, которые выполняют всю работу, а затем использовать перечисление для предоставления всех параметров модели.
например:
class MyXMLModelDelegate implements Model {
public void foo() { /*does foo*/}
...
}
class MyJSONModelDelegate implements Model {
public void foo() { /*does foo*/ }
...
}
public enum Models {
XML(new MyXMLModelDelgate()),
JSON(new MyJSONModelDelegate());
private Model delegate;
public Models(Model delegate) { this.delegate=delegate; }
public void foo() { delegate.foo(); }
}
Я задавал себе тот же вопрос. И я предложил тот же ответ; -)
Теперь я обычно отказываюсь от "принудительного" поведения, я полагаюсь на документацию. Я не нашел ни одного случая, когда аспект синглтона был настолько убедительным, чтобы его нужно было применять всеми способами. Это просто «лучшая практика» для проекта.
Я обычно использую Spring для создания экземпляра такого объекта, и именно конфигурация Spring делает его синглтоном. Безопасно и так просто ... плюс дополнительные преимущества Spring (такие как проксирование, однократная подстановка другого объекта для выполнения некоторых тестов и т.д.)
Это больше ответ на ваш комментарий / пояснение к ответу kts. Неужели настоящая проблема заключается не в использовании шаблона синглтона, а в определении схемы точки расширения затмения (равноденствия), которая позволяет добавлять синглтон?
Я думаю, это невозможно, потому что каждый раз, когда вы вызываете IConfigurationElement. createExecutableExtension вы создаете новый экземпляр. Это совершенно несовместимо с вашим требованием к синглтону. И поэтому вам нужен общедоступный конструктор по умолчанию, чтобы каждый мог создавать экземпляры.
Если вы не можете изменить определение точки расширения так, чтобы плагины предоставляли ModelFactory, а не модель, например
public interface ModelFactory {
public Model getModelInstance();
}
Таким образом, пользователь расширения создаст экземпляр ModelFactory и используйте его для получения синглтона.
Если я не угадала, оставлю комментарий и удалю ответ;)