Я имею дело с рядом объектов сообщения, каждый из которых имеет уникальный идентификатор, соответствующий им. Каждое сообщение может быть создано или из Карты, или из ByteBuffer (сообщения являются двоичными, но мы знаем, как передать и от двоичного представления).
Текущая реализация для построения этих сообщений примерно следующие:
public static Message fromMap(int uuid, Map fields) {
switch (uuid) {
case FIRST_MESSAGE_ID:
return new FirstMessage(fields);
.
.
.
default:
// Error
return null;
}
}
public static Message fromByteBuffer(int uuid, ByteBuffer buffer) {
switch (uuid) {
case FIRST_MESSAGE_ID:
return new FirstMessage(buffer);
.
.
.
default:
// Error
return null;
}
}
Теперь, Эффективный Java Josh Bloch говорит об Объекте 1: Рассмотрите статические методы фабрики вместо конструкторов, и это, кажется, место, где этот шаблон полезен (клиенты непосредственно не получают доступ к конструкторам подтипов сообщения; вместо этого они проходят этот метод). Но мне не нравится то, что мы должны не забыть держать два оператора переключения в курсе (нарушает принцип DRY).
Я ценил бы любое понимание лучшего способа выполнить это; мы не кэшируем объекты (каждый вызов к fromMap, или fromByteBuffer возвратит новый объект), который инвертирует часть преимущества использования статического метода фабрики как это. Что-то об этом коде кажется мне неправильно, таким образом, я хотел бы услышать мысли сообщества о том, является ли это допустимым способом создать новые объекты, или если бы не, каково лучшее решение было бы.
Может быть, вы можете создать интерфейс MessageFactory и реализации IT:
public interface MessageFactory {
Message createMessage(Map<String, Object> fields);
Message createMessage(ByteBuffer buffer);
}
public class FirstMessageFactory implements MessageFactory {
public Message createMessage(Map<String, Object> fields){
return new FirstMessage(fields);
}
public Message createMessage(ByteBuffer buffer){
return new FirstMessage(buffer);
}
}
Далее, метод GetFactoryFromid в том же классе, что и способы выше:
public static MessageFactory getMessageFactoryFromId(int uuid){
switch (uuid) {
case FIRST_MESSAGE_ID:
return new FirstMessageFactory();
...
default:
// Error
return null;
}
}
Однако вместо этого лучше создать hashmap IDS и фабрики, поэтому вам не нужно создавать новый заводский объект каждый раз, когда вы создаете сообщение. Смотрите также комментарий ниже .
И ваши методы:
public static Message fromMap(int uuid, Map<String, Object> fields) {
getMessageFactoryFromId(uuid).createMessage(fields);
}
public static Message fromByteBuffer(int uuid, ByteBuffer buffer) {
getMessageFactoryFromId(uuid).createMessage(buffer);
}
Таким образом, вы используете заводской шаблон, и нет необходимости иметь два раза одни и те же оператор коммутатора.
(не проверил это, так, возможно, некоторые ошибки компиляции / опечатки)
Если у вас есть свои объекты, реализующие интерфейс, объявляющие заводские методы, такие как:
public Message newInstance(Map<String, Object> fields);
public Message newInstance(ByteBuffer buffer);
в статическом вложенном классе, ваш завод может создать карту
, содержащую заводские объекты, индексируемые UUID:
Map map = new HashMap();
map.put(Integer.valueOf(FirstMessage.UUID), new FirstMessage.Factory());
и замените выключатели по поиску карты:
public static Message fromMap(int uuid, Map<String, Object> fields) {
Factory fact = map.get(Integer.valueOf(uuid));
return (null == fact) ? null : fact.newInstance(fields);
}
public static Message fromByteBuffer(int uuid, ByteBuffer buffer) {
Factory fact = map.get(Integer.valueOf(uuid));
return (null == fact) ? null : fact.newInstance(buffer);
}
Это может быть легко расширено для поддержки других методов строительства.
Трудно отсоединить вашу продукцию DB или другой бегущую БД и иметь дело с этим временем простоя, поэтому я почти всегда использую метод резервной копии / восстановления.
Если вы также хотите обеспечить синхронизацию вашего входа в систему, проверьте статью MS KB на использовании хранимых ProC SP_HELP_REVLOGIN .
-121--867648-TEM 1: рассмотрите статические фабричные методы вместо конструкторов
Вы делаете это уже, скрывая конструктор за этим заводским методом, поэтому нет необходимости добавлять еще один заводский метод.
Итак, вы можете сделать это с заводским интерфейсом и картой. (В основном то, что все уже говорят, но с разницей, что вы можете встроить фабрики, используя внутренние классы)
interface MessageFactory {
public Message createWithMap( Map<String,Object> fields );
public Message createWithBuffer( ByteBuffer buffer );
}
Map<MessageFactory> factoriesMap = new HashMap<MessageFactory>() {{
put( FIRST_UUID, new MessageFactory() {
public Message createWithMap( Map<String, Object> fields ) {
return new FirstMessage( fields );
}
public Message createWithBuffer( ByteBuffer buffer ){
return new FirstMessage( buffer );
}
} );
put( SECOND_UUID, new MessageFactory(){
public Message createWithMap( Map<String, Object> fields ) {
return new SecondMessage( fields );
}
public Message createWithBuffer( ByteBuffer buffer ){
return new SecondMessage( buffer );
}
} );
put( THIRD_UUID, new MessageFactory(){
public Message createWithMap( Map<String, Object> fields ) {
return new ThirdMessage( fields );
}
public Message createWithBuffer( ByteBuffer buffer ){
return new ThirdMessage( buffer );
}
} );
...
}};
, и ваши вызова будут превращены в:
public static Message fromMap(int uuid, Map<String, Object> fields) {
return YourClassName.factoriesMap.get( uuid ).createWithMap( fields );
}
public static Message fromByteBuffer(int uuid, ByteBuffer buffer) {
return YourClassName.factoriesMap.get(uuid).createWithBuffer( buffer );
}
, потому что UUID, используемый для выключателя, используется в качестве ключа для заводов. Отказ
Я рекомендую использовать тип enum с абстрактными методами, таким как следующий пример:
enum MessageType {
FIRST_TYPE(FIRST_MESSAGE_ID) {
@Override
Message fromByteBuffer(ByteBuffer buffer) {
return new FirstMessage(buffer);
}
@Override
Message fromMap(Map<String, Object> fields) {
return new FirstMessage(fields);
}
@Override
boolean appliesTo(int uuid) {
return this.uuid == uuid;
}
},
SECOND_TYPE(SECOND_MESSAGE_ID) {
@Override
Message fromByteBuffer(ByteBuffer buffer) {
return new SecondMessage(buffer);
}
@Override
Message fromMap(Map<String, Object> fields) {
return new SecondMessage(fields);
}
@Override
boolean appliesTo(int uuid) {
return this.uuid == uuid;
}
};
protected final int uuid;
MessageType(int uuid) {
this.uuid = uuid;
}
abstract boolean appliesTo(int uuid);
abstract Message fromMap(Map<String, Object> map);
abstract Message fromByteBuffer(ByteBuffer buffer);
}
Таким образом, в ваших существующих статических методах вы можете просто сделать это ...
public static Message fromByteBuffer(int uuid, ByteBuffer buffer) {
Message rslt = null;
for (MessageType y : MessageType.values()) {
if (y.appliesTo(uuid)) {
rslt = y.fromByteBuffer(buffer);
break;
}
}
return rslt;
}
Этот подход Сохраняет ваш статический метод от необходимости знать о поддержке, которые вы поддерживаете и как их построить - вы можете добавить, изменять или удалять сообщения без рефакторов статических методов.
Вы можете изменить сообщение так, чтобы он имеет два метода инициализации, один для карты и один для Bytebuffer (вместо двух версий Cretuctor). Тогда ваш фабричный метод возвращает построенное (но неинициализированное) сообщение, затем вы вызываете инициализацию с картой или ByTeBuffer на возвращенном объекте.
Итак, теперь у вас есть заводский метод, подобный этому: -
private static Message createMessage(int uuid) {
switch (uuid) {
case FIRST_MESSAGE_ID:
return new FirstMessage();
.
.
.
default:
// Error
return null;
}
}
, а затем общественные фабрики методы становятся: -
public static Message fromMap(int uuid, Map<String, Object> fields) {
Message message = createMessage(uuid);
// TODO: null checking etc....
return message.initialize(fields);
}
и
public static Message fromByteBuffer(int uuid, ByteBuffer buffer) {
Message message = createMessage(uuid);
// TODO: null checking etc....
return message.initialize(buffer);
}
Вы должны абстрагироваться от вашего FirstMessage
объекта:
public abstract Message {
// ...
}
Затем кэшировать их на вашем заводе (в отличие от переключателя):
private static final Map<Integer, Class<Message>> MESSAGES = new HashMap<Integer, Class<Message>>();
static {
MESSAGES.put(1, FirstMessage.class);
}
В вашем заводском методе:
public static Message fromMap(UUID uuid, Map<String, Object> fields) {
return MESSAGES.get(uuid).newInstance();
}
В любом случае, это просто идея, вам нужно будет сделать несколько отражений (заставить конструктор) работать, чтобы передать поля.
Вы Может использовать форму абстрактных
шаблон , где у вас будет заводский класс для каждого типа сообщения, который возвращает вам сообщение либо по буферу, либо на карте. Затем вы создаете метод, который возвращает вам соответствующий заводский объект. С возвращенной фабрики вы тогда создаете сообщение.
SQL Server оптимизирован для одновременного выполнения нескольких операций чтения. Единственный раз, когда вы можете столкнуться с взаимоблокировкой, это если у вас много операций обновления происходит в той же таблице, к которой вы пытаетесь получить доступ. Однако в этом случае можно использовать nolock
или даже установить уровень изоляции транзакции на READ UNCOMMITTED
.
Теперь в отношении вашего вопроса многопоточности. В SQL Server используется что-то, называемое волокнами, которые похожи на подпоток. Таким образом, вы не обязательно увидите то же масштабирование потока процессора, которое вы ожидаете увидеть в многопроцессорной среде. Хотя SQL Server имеет доступ к определенному числу потоков, существует максимальное количество волокон, которые также могут использоваться. Вот почему вы можете иметь 1000 клиентов, имеющих доступ к одному и тому же серверу одновременно даже на небольших коробках.
Если вы действительно хотите попасть в планирование потоков/оптоволокна, вам нужно будет найти хорошего гаек и болтов SQL Server, который действительно действительно получает его, как это сложно.
Просто поймите, что sql server оптимизирован для этого, и вам не нужно объединять его тестирование каким-либо образом, так как это уже было доказано с помощью инструментов, которые вы, вероятно, не сможете воссоздать.
-121--3802394-Необходимо создать мутатор для изменения частных переменных-членов.
class example{
private string myColor;
public void changeColor(string newColor){
myColor = newColor;
}
}
-121--2296102- Есть ли способ преобразовать ByteBuffer в карту или что-то еще? Было бы неплохо преобразовать входные данные в нормализованную форму и применить уникальный переключатель.
Если вы хотите получить сообщение и отформатировать его с определенными значениями (например, «Таблица: taureName не имеет столбца с именем: colName»), вы можете преобразовать ByteBuffer в карту и вызвать первый метод. Если вам нужен новый идентификатор msgId, вы расширяете только метод startMap Map.
Это что-то вроде факторинга общей части.