Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-静态工厂方法和开关语句_Java_Factory - Fatal编程技术网

Java-静态工厂方法和开关语句

Java-静态工厂方法和开关语句,java,factory,Java,Factory,我处理的是一组消息对象,每个对象都有一个与之对应的唯一标识符。每个消息都可以从映射或ByteBuffer构造(消息是二进制的,但我们知道如何在二进制表示之间进行转换) 构建这些消息的当前实现大致如下: public static Message fromMap(int uuid, Map<String, Object> fields) { switch (uuid) { case FIRST_MESSAGE_ID: return new First

我处理的是一组消息对象,每个对象都有一个与之对应的唯一标识符。每个消息都可以从映射或ByteBuffer构造(消息是二进制的,但我们知道如何在二进制表示之间进行转换)

构建这些消息的当前实现大致如下:

public static Message fromMap(int uuid, Map<String, Object> 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;
    }
}
来自映射的公共静态消息(int-uuid,映射字段){
交换机(uuid){
案例优先\u消息\u ID:
返回新的第一条消息(字段);
.
.
.
违约:
//错误
返回null;
}
}
来自ByteBuffer的公共静态消息(int uuid,ByteBuffer缓冲区){
交换机(uuid){
案例优先\u消息\u ID:
返回新的第一条消息(缓冲区);
.
.
.
违约:
//错误
返回null;
}
}

现在,讨论第1项:考虑静态工厂方法而不是构造函数,这似乎是一个有用的模式(客户端不直接访问消息子类型的构造函数,而是通过这个方法)。但我不喜欢这样一个事实:我们必须记住更新两个switch语句(违反了原则)


我希望能够深入了解实现这一目标的最佳方式;我们不缓存对象(每次调用fromMap或fromByteBuffer都将返回一个新对象),这否定了使用这样的静态工厂方法的一些好处。我觉得这段代码有些地方不对,所以我很想听听社区的想法,看看这是否是构造新对象的有效方法,或者如果不是的话,最好的解决方案是什么。

也许你可以创建一个接口MessageFactory并实现它:

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);
  }

}
但是,与此相反,最好创建一个包含ID和工厂的Hashmap,这样就不必每次创建消息时都创建一个新的工厂对象。另见

你的方法是:

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);
}
来自映射的公共静态消息(int-uuid,映射字段){
getMessageFactoryFromId(uuid).createMessage(字段);
}
来自ByteBuffer的公共静态消息(int uuid,ByteBuffer缓冲区){
getMessageFactoryFromId(uuid).createMessage(缓冲区);
}
这样,您使用的是工厂模式,不需要两次使用相同的switch语句


(没有测试这一点,因此可能会出现一些编译错误/打字错误)

您可以使用
AbstractFactory
模式,其中每个消息类型都有一个factory类,它通过缓冲区或映射返回消息。然后创建一个返回相应factory对象的方法。然后从返回的工厂创建消息。

是否有方法将ByteBuffer转换为地图或其他内容?如果您将输入转换为规范化形式并应用一个唯一的开关,那就太好了

如果您要做的是获取消息并使用特定值对其进行格式化(如“table:tableName没有名为:colName的列”),则可以将ByteBuffer转换为映射并调用第一个方法。如果需要新的msgId,则只扩展fromMap方法


这类似于分解公共部分。

如果您的对象实现了一个声明工厂方法的接口,如:

public Message newInstance(Map<String, Object> fields);
public Message newInstance(ByteBuffer buffer);
并通过地图查找替换交换机:

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);
}
来自映射的公共静态消息(int-uuid,映射字段){
Factory fact=map.get(Integer.valueOf(uuid));
返回值(null==fact)?null:fact.newInstance(字段);
}
来自ByteBuffer的公共静态消息(int uuid,ByteBuffer缓冲区){
Factory fact=map.get(Integer.valueOf(uuid));
返回值(null==fact)?null:fact.newInstance(缓冲区);
}

这可以很容易地扩展以支持其他构造方法。

我建议将枚举类型与抽象方法一起使用,例如以下示例:

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);

}

这种方法使静态方法不必知道您支持的消息类型以及如何构建它们——您可以添加、修改或删除消息,而无需重构静态方法。

您应该抽象您的
FirstMessage
对象:

public abstract Message {
   // ...
}
然后将它们缓存在工厂中(与交换机相反):

private static final Map MESSAGES=new HashMap();
静止的{
MESSAGES.put(1,FirstMessage.class);
}
在您的工厂方法中:

public static Message fromMap(UUID uuid, Map<String, Object> fields) {
    return MESSAGES.get(uuid).newInstance();
}
来自映射的公共静态消息(UUID UUID,映射字段){
返回MESSAGES.get(uuid.newInstance();
}

无论如何,这只是一个想法,您必须做一些反射(让构造函数)工作来传递字段。

您可以修改消息,使其具有两个初始化方法,一个用于Map,一个用于ByteBuffer(而不是两个constructor版本)。然后,工厂方法返回构造(但未初始化)消息,然后使用映射或ByteBuffer对返回的对象调用initialize

现在有了一个工厂方法,如下所示:-

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);
}

TEM 1:考虑静态工厂方法,而不考虑构造函数< /P> 通过将构造函数隐藏在工厂方法后面,您已经做到了这一点,因此无需在此处添加另一个工厂方法

所以你可以用一个工厂界面和一个地图来完成。(基本上每个人都在说,但不同的是,您可以使用内部类内联工厂)

接口消息工厂{
公共消息createWithMap(映射字段);
公共消息createWithBuffer(ByteBuffer buffer);
}
Map factoriemap=new HashMap(){{
put(第一个ID,新的MessageFactory(){
公共消息createWithMap(映射字段){
返回新的第一条消息(字段);
}
公共消息createWithBuffer(ByteBuffer缓冲区){
返回新的第一条消息(缓冲区);
}
} );
put(第二个id,新的MessageFactory(){
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();
}
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);
}
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 );
}