Index: /trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/Main.java	(revision 12775)
+++ /trunk/src/org/openstreetmap/josm/Main.java	(revision 12776)
@@ -54,4 +54,5 @@
 import org.openstreetmap.josm.tools.JosmRuntimeException;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.Platform;
 import org.openstreetmap.josm.tools.PlatformHook;
 import org.openstreetmap.josm.tools.PlatformHookOsx;
@@ -772,20 +773,5 @@
      */
     public static void determinePlatformHook() {
-        String os = System.getProperty("os.name");
-        if (os == null) {
-            Logging.warn("Your operating system has no name, so I'm guessing its some kind of *nix.");
-            platform = new PlatformHookUnixoid();
-        } else if (os.toLowerCase(Locale.ENGLISH).startsWith("windows")) {
-            platform = new PlatformHookWindows();
-        } else if ("Linux".equals(os) || "Solaris".equals(os) ||
-                "SunOS".equals(os) || "AIX".equals(os) ||
-                "FreeBSD".equals(os) || "NetBSD".equals(os) || "OpenBSD".equals(os)) {
-            platform = new PlatformHookUnixoid();
-        } else if (os.toLowerCase(Locale.ENGLISH).startsWith("mac os x")) {
-            platform = new PlatformHookOsx();
-        } else {
-            Logging.warn("I don't know your operating system '"+os+"', so I'm guessing its some kind of *nix.");
-            platform = new PlatformHookUnixoid();
-        }
+        platform = Platform.determinePlatform().accept(PlatformHook.CONSTRUCT_FROM_PLATFORM);
     }
 
Index: /trunk/src/org/openstreetmap/josm/data/projection/datum/NTV2GridShiftFileWrapper.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/datum/NTV2GridShiftFileWrapper.java	(revision 12775)
+++ /trunk/src/org/openstreetmap/josm/data/projection/datum/NTV2GridShiftFileWrapper.java	(revision 12776)
@@ -5,7 +5,12 @@
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.io.CachedFile;
+import org.openstreetmap.josm.tools.Platform;
+import org.openstreetmap.josm.tools.PlatformVisitor;
 
 /**
@@ -29,4 +34,26 @@
 
     /**
+     * Lists default directories where the ntv2 shift files (NAD) for the proj4
+     * library would be located on different platforms.
+     */
+    public static final PlatformVisitor<List<File>> DEFAULT_PROJ4_NTV2_SHIFT_DIRS =
+            new PlatformVisitor<List<File>>() {
+        @Override
+        public List<File> visitUnixoid() {
+            return Arrays.asList(new File("/usr/local/share/proj"), new File("/usr/share/proj"));
+        }
+
+        @Override
+        public List<File> visitWindows() {
+            return Arrays.asList(new File("C:\\PROJ\\NAD"));
+        }
+
+        @Override
+        public List<File> visitOsx() {
+            return Collections.emptyList();
+        }
+    };
+
+    /**
      * Returns the actual {@link NTV2GridShiftFile} behind this wrapper.
      * The grid file is only loaded once, when first accessed.
@@ -38,5 +65,5 @@
             File grid = null;
             // Check is the grid is installed in default PROJ.4 directories
-            for (File dir : Main.platform.getDefaultProj4NadshiftDirectories()) {
+            for (File dir : Platform.determinePlatform().accept(DEFAULT_PROJ4_NTV2_SHIFT_DIRS)) {
                 File file = new File(dir, gridFileName);
                 if (file.exists() && file.isFile()) {
Index: /trunk/src/org/openstreetmap/josm/tools/Platform.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/Platform.java	(revision 12776)
+++ /trunk/src/org/openstreetmap/josm/tools/Platform.java	(revision 12776)
@@ -0,0 +1,67 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.tools;
+
+import java.util.Locale;
+
+/**
+ * Enum listing the supported platforms (operating system families).
+ * @since 12776
+ */
+public enum Platform {
+
+    UNIXOID {
+        @Override
+        public <T> T accept(PlatformVisitor<T> visitor) {
+            return visitor.visitUnixoid();
+        }
+    },
+    WINDOWS {
+        @Override
+        public <T> T accept(PlatformVisitor<T> visitor) {
+            return visitor.visitWindows();
+        }
+    },
+    OSX {
+        @Override
+        public <T> T accept(PlatformVisitor<T> visitor) {
+            return visitor.visitOsx();
+        }
+    };
+
+    private static Platform platform;
+
+    /**
+     * Support for the visitor pattern.
+     * @param <T> type that will be the result of the visiting operation
+     * @param visitor the visitor
+     * @return result of the operation
+     */
+    public abstract <T> T accept(PlatformVisitor<T> visitor);
+
+    /**
+     * Identifies the current operating system family.
+     * @return the the current operating system family
+     */
+    public static Platform determinePlatform() {
+        if (platform == null) {
+            String os = System.getProperty("os.name");
+            if (os == null) {
+                Logging.warn("Your operating system has no name, so I'm guessing its some kind of *nix.");
+                platform = Platform.UNIXOID;
+            } else if (os.toLowerCase(Locale.ENGLISH).startsWith("windows")) {
+                platform = Platform.WINDOWS;
+            } else if ("Linux".equals(os) || "Solaris".equals(os) ||
+                    "SunOS".equals(os) || "AIX".equals(os) ||
+                    "FreeBSD".equals(os) || "NetBSD".equals(os) || "OpenBSD".equals(os)) {
+                platform = Platform.UNIXOID;
+            } else if (os.toLowerCase(Locale.ENGLISH).startsWith("mac os x")) {
+                platform = Platform.OSX;
+            } else {
+                Logging.warn("I don't know your operating system '"+os+"', so I'm guessing its some kind of *nix.");
+                platform = Platform.UNIXOID;
+            }
+        }
+        return platform;
+    }
+
+}
Index: /trunk/src/org/openstreetmap/josm/tools/PlatformHook.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/PlatformHook.java	(revision 12775)
+++ /trunk/src/org/openstreetmap/josm/tools/PlatformHook.java	(revision 12776)
@@ -20,4 +20,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.projection.datum.NTV2GridShiftFileWrapper;
 import org.openstreetmap.josm.io.CertificateAmendment.CertAmend;
 import org.openstreetmap.josm.tools.date.DateUtils;
@@ -29,4 +30,30 @@
  */
 public interface PlatformHook {
+
+    /**
+     * Visitor to construct a PlatformHook from a given {@link Platform} object.
+     */
+    public static final PlatformVisitor<PlatformHook> CONSTRUCT_FROM_PLATFORM = new PlatformVisitor<PlatformHook>() {
+        @Override
+        public PlatformHook visitUnixoid() {
+            return new PlatformHookUnixoid();
+        }
+
+        @Override
+        public PlatformHook visitWindows() {
+            return new PlatformHookWindows();
+        }
+
+        @Override
+        public PlatformHook visitOsx() {
+            return new PlatformHookUnixoid();
+        }
+    };
+
+    /**
+     * Get the platform corresponding to this platform hook.
+     * @return the platform corresponding to this platform hook
+     */
+    Platform getPlatform();
 
     /**
@@ -231,5 +258,7 @@
      * @since 11642
      */
-    List<File> getDefaultProj4NadshiftDirectories();
+    default List<File> getDefaultProj4NadshiftDirectories() {
+        return getPlatform().accept(NTV2GridShiftFileWrapper.DEFAULT_PROJ4_NTV2_SHIFT_DIRS);
+    }
 
     /**
Index: /trunk/src/org/openstreetmap/josm/tools/PlatformHookOsx.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/PlatformHookOsx.java	(revision 12775)
+++ /trunk/src/org/openstreetmap/josm/tools/PlatformHookOsx.java	(revision 12776)
@@ -15,5 +15,4 @@
 import java.lang.reflect.Proxy;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
@@ -32,4 +31,9 @@
 
     private NativeOsCallback osCallback;
+
+    @Override
+    public Platform getPlatform() {
+        return Platform.OSX;
+    }
 
     @Override
@@ -423,8 +427,3 @@
                 Main.pref.getJOSMDirectoryBaseName());
     }
-
-    @Override
-    public List<File> getDefaultProj4NadshiftDirectories() {
-        return Collections.emptyList();
-    }
 }
Index: /trunk/src/org/openstreetmap/josm/tools/PlatformHookUnixoid.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/PlatformHookUnixoid.java	(revision 12775)
+++ /trunk/src/org/openstreetmap/josm/tools/PlatformHookUnixoid.java	(revision 12776)
@@ -22,5 +22,4 @@
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
-import java.util.List;
 import java.util.Locale;
 
@@ -66,4 +65,9 @@
             "尚未安裝"                // zh_TW
     };
+
+    @Override
+    public Platform getPlatform() {
+        return Platform.UNIXOID;
+    }
 
     @Override
@@ -422,9 +426,4 @@
 
     @Override
-    public List<File> getDefaultProj4NadshiftDirectories() {
-        return Arrays.asList(new File("/usr/local/share/proj"), new File("/usr/share/proj"));
-    }
-
-    @Override
     public X509Certificate getX509Certificate(CertAmend certAmend)
             throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
Index: /trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java	(revision 12775)
+++ /trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java	(revision 12776)
@@ -58,5 +58,4 @@
 import java.security.spec.X509EncodedKeySpec;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Enumeration;
@@ -155,4 +154,9 @@
 
     private String oSBuildNumber;
+
+    @Override
+    public Platform getPlatform() {
+        return Platform.WINDOWS;
+    }
 
     @Override
@@ -673,8 +677,3 @@
         return def;
     }
-
-    @Override
-    public List<File> getDefaultProj4NadshiftDirectories() {
-        return Arrays.asList(new File("C:\\PROJ\\NAD"));
-    }
 }
Index: /trunk/src/org/openstreetmap/josm/tools/PlatformVisitor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/PlatformVisitor.java	(revision 12776)
+++ /trunk/src/org/openstreetmap/josm/tools/PlatformVisitor.java	(revision 12776)
@@ -0,0 +1,27 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.tools;
+
+/**
+ * Visitor, to be used with {@link Platform}.
+ * @param <T> type that will be the result of the visiting operation
+ * @since 12776
+ */
+public interface PlatformVisitor<T> {
+    /**
+     * Visit {@link Platform#UNIXOID}
+     * @return result of the operation
+     */
+    T visitUnixoid();
+
+    /**
+     * Visit {@link Platform#WINDOWS}
+     * @return result of the operation
+     */
+    T visitWindows();
+
+    /**
+     * Visit {@link Platform#OSX}
+     * @return result of the operation
+     */
+    T visitOsx();
+}
