diff --git a/Code/Mantid/Framework/Geometry/CMakeLists.txt b/Code/Mantid/Framework/Geometry/CMakeLists.txt
index 4f6990ac989db80a043e6c03e92bfc2758985d88..f192ebbd483f9d9ff05d6661a9f402e3a982145b 100644
--- a/Code/Mantid/Framework/Geometry/CMakeLists.txt
+++ b/Code/Mantid/Framework/Geometry/CMakeLists.txt
@@ -6,6 +6,7 @@ set ( SRC_FILES
 	src/Crystal/NiggliCell.cpp
 	src/Crystal/OrientedLattice.cpp
 	src/Crystal/PointGroup.cpp
+	src/Crystal/PointGroupFactory.cpp
 	src/Crystal/ReducedCell.cpp
 	src/Crystal/ReflectionCondition.cpp
 	src/Crystal/ScalarUtils.cpp
@@ -107,6 +108,7 @@ set ( INC_FILES
 	inc/MantidGeometry/Crystal/NiggliCell.h
 	inc/MantidGeometry/Crystal/OrientedLattice.h
 	inc/MantidGeometry/Crystal/PointGroup.h
+	inc/MantidGeometry/Crystal/PointGroupFactory.h
 	inc/MantidGeometry/Crystal/ReducedCell.h
 	inc/MantidGeometry/Crystal/ReflectionCondition.h
 	inc/MantidGeometry/Crystal/ScalarUtils.h
@@ -249,6 +251,7 @@ set ( TEST_FILES
 	ParameterMapTest.h
 	ParametrizedComponentTest.h
 	PlaneTest.h
+	PointGroupFactoryTest.h
 	PointGroupTest.h
 	PolygonEdgeTest.h
 	QuadrilateralTest.h
diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/PointGroupFactory.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/PointGroupFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..c4957d86cb772ccf697cc4349fdf3676fa5ca40c
--- /dev/null
+++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/PointGroupFactory.h
@@ -0,0 +1,99 @@
+#ifndef MANTID_GEOMETRY_POINTGROUPFACTORY_H_
+#define MANTID_GEOMETRY_POINTGROUPFACTORY_H_
+
+#include "MantidGeometry/DllConfig.h"
+#include "MantidKernel/DynamicFactory.h"
+#include "MantidKernel/SingletonHolder.h"
+#include "MantidGeometry/Crystal/PointGroup.h"
+
+namespace Mantid
+{
+namespace Geometry
+{
+  /** PointGroupFactory
+
+    A factory for point groups. Point group objects can be constructed by
+    supplying the Hermann-Mauguin-symbol like this:
+
+        PointGroup_sptr cubic = PointGroupFactory::Instance().createPointgroup("m-3m");
+
+    Furthermore it's possible to query available point groups
+
+      @author Michael Wedel, Paul Scherrer Institut - SINQ
+      @date 09/09/2014
+
+      Copyright © 2014 PSI-MSS
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://github.com/mantidproject/mantid>
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+  */
+  class MANTID_GEOMETRY_DLL PointGroupFactoryImpl : public Kernel::DynamicFactory<PointGroup>
+  {
+  public:
+      PointGroup_sptr createPointgroup(const std::string &hmSymbol) const;
+
+      std::vector<std::string> getAllPointGroupSymbols() const;
+      std::vector<std::string> getAllPointGroupSymbols(const PointGroup::CrystalSystem &crystalSystem) const;
+
+      template <class C>
+      void subscribePointgroup()
+      {
+          Kernel::Instantiator<C, PointGroup> *instantiator = new Kernel::Instantiator<C, PointGroup>;
+          PointGroup_sptr temporaryPointgroup = instantiator->createInstance();
+          std::string hmSymbol = temporaryPointgroup->getSymbol();
+
+          subscribe(hmSymbol, instantiator);
+
+          addToCrystalSystemMap(temporaryPointgroup->crystalSystem(), hmSymbol);
+      }
+
+      void unsubscribePointgroup(const std::string &hmSymbol)
+      {
+          unsubscribe(hmSymbol);
+          removeFromCrystalSystemMap(hmSymbol);
+      }
+
+  private:
+      friend struct Mantid::Kernel::CreateUsingNew<PointGroupFactoryImpl>;
+
+      PointGroupFactoryImpl();
+      void addToCrystalSystemMap(const PointGroup::CrystalSystem &crystalSystem, const std::string &hmSymbol);
+      void removeFromCrystalSystemMap(const std::string &hmSymbol);
+
+      std::map<std::string, PointGroup::CrystalSystem> m_crystalSystemMap;
+  };
+
+// This is taken from FuncMinimizerFactory
+#ifdef _WIN32
+    template class MANTID_GEOMETRY_DLL Mantid::Kernel::SingletonHolder<PointGroupFactory>;
+#endif
+
+typedef Mantid::Kernel::SingletonHolder<PointGroupFactoryImpl> PointGroupFactory;
+
+
+} // namespace Geometry
+} // namespace Mantid
+
+#define DECLARE_POINTGROUP(classname) \
+        namespace { \
+    Mantid::Kernel::RegistrationHelper register_pointgroup_##classname( \
+  ((Mantid::Geometry::PointGroupFactory::Instance().subscribePointgroup<classname>()) \
+    , 0)); \
+    }
+
+#endif  /* MANTID_GEOMETRY_POINTGROUPFACTORY_H_ */
diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/PointGroup.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/PointGroup.cpp
index debd664c104a4a82d318a46f83f169243d67abd4..98b9d3837de098d0900f3e879a9de2abeb421860 100644
--- a/Code/Mantid/Framework/Geometry/src/Crystal/PointGroup.cpp
+++ b/Code/Mantid/Framework/Geometry/src/Crystal/PointGroup.cpp
@@ -4,6 +4,8 @@
 #include <set>
 #include <boost/make_shared.hpp>
 
+#include "MantidGeometry/Crystal/PointGroupFactory.h"
+
 namespace Mantid
 {
 namespace Geometry
@@ -578,20 +580,13 @@ namespace Geometry
   /** @return a vector with all possible PointGroup objects */
   std::vector<PointGroup_sptr> getAllPointGroups()
   {
+    std::vector<std::string> allSymbols = PointGroupFactory::Instance().getAllPointGroupSymbols();
+
     std::vector<PointGroup_sptr> out;
-    out.push_back( boost::make_shared<PointGroupLaue1>() );
-    out.push_back( boost::make_shared<PointGroupLaue2>() );
-    out.push_back( boost::make_shared<PointGroupLaue3>() );
-    out.push_back( boost::make_shared<PointGroupLaue4>() );
-    out.push_back( boost::make_shared<PointGroupLaue5>() );
-    out.push_back( boost::make_shared<PointGroupLaue6>() );
-    out.push_back( boost::make_shared<PointGroupLaue7>() );
-    out.push_back( boost::make_shared<PointGroupLaue8>() );
-    out.push_back( boost::make_shared<PointGroupLaue9>() );
-    out.push_back( boost::make_shared<PointGroupLaue10>() );
-    out.push_back( boost::make_shared<PointGroupLaue11>() );
-    out.push_back( boost::make_shared<PointGroupLaue12>() );
-    out.push_back( boost::make_shared<PointGroupLaue13>() );
+    for(auto it = allSymbols.begin(); it != allSymbols.end(); ++it) {
+        out.push_back(PointGroupFactory::Instance().create(*it));
+    }
+
     return out;
   }
 
@@ -607,7 +602,19 @@ namespace Geometry
       return map;
   }
 
-
+  DECLARE_POINTGROUP(PointGroupLaue1)
+  DECLARE_POINTGROUP(PointGroupLaue2)
+  DECLARE_POINTGROUP(PointGroupLaue3)
+  DECLARE_POINTGROUP(PointGroupLaue4)
+  DECLARE_POINTGROUP(PointGroupLaue5)
+  DECLARE_POINTGROUP(PointGroupLaue6)
+  DECLARE_POINTGROUP(PointGroupLaue7)
+  DECLARE_POINTGROUP(PointGroupLaue8)
+  DECLARE_POINTGROUP(PointGroupLaue9)
+  DECLARE_POINTGROUP(PointGroupLaue10)
+  DECLARE_POINTGROUP(PointGroupLaue11)
+  DECLARE_POINTGROUP(PointGroupLaue12)
+  DECLARE_POINTGROUP(PointGroupLaue13)
 
 } // namespace Mantid
 } // namespace Geometry
diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/PointGroupFactory.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/PointGroupFactory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..874123aa7331352743170455a26e3a404239a663
--- /dev/null
+++ b/Code/Mantid/Framework/Geometry/src/Crystal/PointGroupFactory.cpp
@@ -0,0 +1,58 @@
+#include "MantidGeometry/Crystal/PointGroupFactory.h"
+
+#include "MantidKernel/LibraryManager.h"
+
+namespace Mantid
+{
+namespace Geometry
+{
+
+PointGroup_sptr PointGroupFactoryImpl::createPointgroup(const std::string &hmSymbol) const
+{
+    return create(hmSymbol);
+}
+
+std::vector<std::string> PointGroupFactoryImpl::getAllPointGroupSymbols() const
+{
+    std::vector<std::string> pointGroups;
+
+    for(auto it = m_crystalSystemMap.begin(); it != m_crystalSystemMap.end(); ++it) {
+        pointGroups.push_back(it->first);
+    }
+
+    return pointGroups;
+}
+
+std::vector<std::string> PointGroupFactoryImpl::getAllPointGroupSymbols(const PointGroup::CrystalSystem &crystalSystem) const
+{
+    std::vector<std::string> pointGroups;
+
+    for(auto it = m_crystalSystemMap.begin(); it != m_crystalSystemMap.end(); ++it) {
+        if(it->second == crystalSystem) {
+            pointGroups.push_back(it->first);
+        }
+    }
+
+    return pointGroups;
+}
+
+PointGroupFactoryImpl::PointGroupFactoryImpl() : Kernel::DynamicFactory<PointGroup>()
+{
+    Kernel::LibraryManager::Instance();
+}
+
+void PointGroupFactoryImpl::addToCrystalSystemMap(const PointGroup::CrystalSystem &crystalSystem, const std::string &hmSymbol)
+{
+    m_crystalSystemMap.insert(std::make_pair(hmSymbol, crystalSystem));
+}
+
+void PointGroupFactoryImpl::removeFromCrystalSystemMap(const std::string &hmSymbol)
+{
+    auto it = m_crystalSystemMap.find(hmSymbol);
+    m_crystalSystemMap.erase(it);
+}
+
+
+
+} // namespace Geometry
+} // namespace Mantid
diff --git a/Code/Mantid/Framework/Geometry/test/PointGroupFactoryTest.h b/Code/Mantid/Framework/Geometry/test/PointGroupFactoryTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..ec4414fb80caab2be31c6dc514ee1692fa38b4e6
--- /dev/null
+++ b/Code/Mantid/Framework/Geometry/test/PointGroupFactoryTest.h
@@ -0,0 +1,146 @@
+#ifndef MANTID_GEOMETRY_POINTGROUPFACTORYTEST_H_
+#define MANTID_GEOMETRY_POINTGROUPFACTORYTEST_H_
+
+#include <cxxtest/TestSuite.h>
+
+#include "MantidGeometry/Crystal/PointGroupFactory.h"
+#include "MantidGeometry/Crystal/PointGroup.h"
+#include "MantidKernel/Exception.h"
+
+
+using Mantid::Geometry::PointGroupFactoryImpl;
+using namespace Mantid::Geometry;
+
+
+/* For testing the factory, three fake point groups are defined
+ * and registered in the factory (see below).
+ *
+ * When the test is destroyed, these are explicitly unregistered,
+ * so they don't interfere with other tests.
+ */
+class TestPointGroupCubicA : public PointGroup
+{
+public:
+    TestPointGroupCubicA() : PointGroup("cubicA")
+    { }
+    ~TestPointGroupCubicA() { }
+
+    std::string getName() const { return "cubicA (test)"; }
+    bool isEquivalent(const Mantid::Kernel::V3D &hkl, const Mantid::Kernel::V3D &hkl2) const
+    {
+        UNUSED_ARG(hkl);
+        UNUSED_ARG(hkl2);
+
+        return false;
+    }
+
+    PointGroup::CrystalSystem crystalSystem() const { return PointGroup::Cubic; }
+};
+
+class TestPointGroupCubicB : public PointGroup
+{
+public:
+    TestPointGroupCubicB() : PointGroup("cubicB")
+    { }
+    ~TestPointGroupCubicB() { }
+
+    std::string getName() const { return "cubicB (test)"; }
+    bool isEquivalent(const Mantid::Kernel::V3D &hkl, const Mantid::Kernel::V3D &hkl2) const
+    {
+        UNUSED_ARG(hkl);
+        UNUSED_ARG(hkl2);
+
+        return false;
+    }
+
+    PointGroup::CrystalSystem crystalSystem() const { return PointGroup::Cubic; }
+};
+
+class TestPointGroupTriclinic : public PointGroup
+{
+public:
+    TestPointGroupTriclinic() : PointGroup("triclinic")
+    { }
+    ~TestPointGroupTriclinic() { }
+
+    std::string getName() const { return "triclinic (test)"; }
+    bool isEquivalent(const Mantid::Kernel::V3D &hkl, const Mantid::Kernel::V3D &hkl2) const
+    {
+        UNUSED_ARG(hkl);
+        UNUSED_ARG(hkl2);
+
+        return false;
+    }
+
+    PointGroup::CrystalSystem crystalSystem() const { return PointGroup::Triclinic; }
+};
+
+DECLARE_POINTGROUP(TestPointGroupCubicA);
+DECLARE_POINTGROUP(TestPointGroupCubicB);
+DECLARE_POINTGROUP(TestPointGroupTriclinic);
+
+
+class PointGroupFactoryTest : public CxxTest::TestSuite
+{
+public:
+  // This pair of boilerplate methods prevent the suite being created statically
+  // This means the constructor isn't called when running other tests
+  static PointGroupFactoryTest *createSuite() { return new PointGroupFactoryTest(); }
+  static void destroySuite( PointGroupFactoryTest *suite ) { delete suite; }
+
+  ~PointGroupFactoryTest()
+  {
+      // Unsubscribing the fake point groups
+      PointGroupFactory::Instance().unsubscribePointgroup("cubicA");
+      PointGroupFactory::Instance().unsubscribePointgroup("cubicB");
+      PointGroupFactory::Instance().unsubscribePointgroup("triclinic");
+  }
+
+  void testCreatePointGroup()
+  {
+      TS_ASSERT_THROWS_NOTHING(PointGroupFactory::Instance().createPointgroup("cubicA"));
+      TS_ASSERT_THROWS_NOTHING(PointGroupFactory::Instance().createPointgroup("cubicB"));
+      TS_ASSERT_THROWS_NOTHING(PointGroupFactory::Instance().createPointgroup("triclinic"));
+
+      TS_ASSERT_THROWS(PointGroupFactory::Instance().createPointgroup("cubicC"), Mantid::Kernel::Exception::NotFoundError);
+  }
+
+  void testGetAllPointGroupSymbols()
+  {
+      std::vector<std::string> symbols = PointGroupFactory::Instance().getAllPointGroupSymbols();
+
+      TS_ASSERT_DIFFERS(findString(symbols, "cubicA"), symbols.end());
+      TS_ASSERT_DIFFERS(findString(symbols, "cubicB"), symbols.end());
+      TS_ASSERT_DIFFERS(findString(symbols, "triclinic"), symbols.end());
+  }
+
+  void testGetAllPointGroupSymbolsCrystalSystems()
+  {
+      std::vector<std::string> cubic = PointGroupFactory::Instance().getAllPointGroupSymbols(PointGroup::Cubic);
+      TS_ASSERT_DIFFERS(findString(cubic, "cubicA"), cubic.end());
+      TS_ASSERT_DIFFERS(findString(cubic, "cubicB"), cubic.end());
+
+      std::vector<std::string> triclinic = PointGroupFactory::Instance().getAllPointGroupSymbols(PointGroup::Triclinic);
+      TS_ASSERT_DIFFERS(findString(triclinic, "triclinic"), triclinic.end());
+  }
+
+  void testUnsubscribePointGroup()
+  {
+      TS_ASSERT_THROWS_NOTHING(PointGroupFactory::Instance().createPointgroup("cubicA"));
+
+      PointGroupFactory::Instance().unsubscribePointgroup("cubicA");
+      TS_ASSERT_THROWS(PointGroupFactory::Instance().create("cubicA"), Mantid::Kernel::Exception::NotFoundError);
+
+      PointGroupFactory::Instance().subscribePointgroup<TestPointGroupCubicA>();
+      TS_ASSERT_THROWS_NOTHING(PointGroupFactory::Instance().createPointgroup("cubicA"));
+  }
+
+private:
+  std::vector<std::string>::const_iterator findString(const std::vector<std::string> &vector, const std::string &searchString)
+  {
+      return std::find(vector.begin(), vector.end(), searchString);
+  }
+};
+
+
+#endif /* MANTID_GEOMETRY_POINTGROUPFACTORYTEST_H_ */