静态工厂方法问题!

时间:2011-04-05 12:22:31

标签: java methods static factory

在这个网站中它说每次都没有创建一个新对象,这会带来效率,但是我可以看到每次在静态方法中都会创建一个对象。

  

不需要创建新对象   在每次调用时 - 对象都可以   如有必要,可以缓存和重用。

http://www.javapractices.com/topic/TopicAction.do?Id=21

那么为什么静态工厂方法如此高效?

不写这样的东西:Object obj = new Object就像我做了Object obj = Someclass.GetObj();

class Someclass
{
   public static Object GetObj()
   {
     return new Object
   }
}

有缓存,但无论如何都会创建一个新对象......

6 个答案:

答案 0 :(得分:3)

对象可以缓存并重用。它们并非总是如此。还有许多其他优点,例如:

  • 更好地命名方法
  • 返回子类

有效Java中有一个项目,所以请继续阅读。无论如何,这本书是必读的。

更新:正如我所说,对象可以被缓存。但这取决于实施。您显示的那个不会缓存它们。彼得所显示的那个就是他们。你有这个选择。使用构造函数 - 你没有。

答案 1 :(得分:1)

使用new Object()时,必须创建一个新的对象。

如果您使用静态工厂,则可以选择创建新对象,也可以重复使用现有对象。

一个简单的示例是使用Integer.valueOf(int)而不是new Integer(int)。静态工厂有一个小整数的缓存,可以保存到很大一部分整数的创建。对于某些用例,这可以是所有使用的整数。后一种情况总是会创建一个效率相对较低的新对象。

答案 2 :(得分:1)

它们更灵活 - 例如,如果新对象的输入参数无效,则可以返回null或一些空对象实现(=实例,它不执行任何操作,但不会通过NullPointerException中断代码),或者,如前所述,您可以缓存创建的实例。使用工厂方法而不是构造函数还有另一个好处 - 如果有多个构造函数包含大量可选参数,您可以将它们命名为任意名称,这样可以更具可读性。

编辑:如果你只想使用一个实例,你可以使用这个简单的工厂:

class Someclass{
  private static Object o=new Object();

  public static Object getObj(){
    return o;
  }
}

答案 3 :(得分:1)

您提供的链接提供了对工厂模式的非常不同的解释。通常,工厂模式用于获取实现相同接口但为同一合同提供不同行为的类的实例。它允许我们在运行时选择不同的实现。看看这里的例子:

http://www.allapplabs.com/java_design_patterns/factory_pattern.htm

工厂模式通常不用于缓存对象。定义单例模式以确保只创建一个对象实例。

答案 4 :(得分:0)

这个想法是你用它们作为一种策略。如果以后要实现缓存,只需更改该方法并将其添加到其中即可。比较一下,将“new Bla()”分散在整个代码中,并尝试为Bla类实现缓存。

由于该方法是静态的,通常只有几行代码,这意味着它可以在编译时解析,甚至内联。

因此,根本没有使用“new Bla()”代替工厂方法的优势。

答案 5 :(得分:0)

在某些情况下使用工厂,您可以使代码更灵活,更快速,更易读。

例如,想象一下,你必须编写从url下载一些数据的类

public class WavAudio {
      private byte[] raw;
      private static HashMap<String,WavAudio> cache;
      private WavAudio(byte[] raw){
          this.raw=raw;
      }
      public static loadFromUrl(String someUrl){
          //If data has been loaded previously we don't have to do this more (faster..)
          if (cache.containsKey(someUrl))
               return cache.get(someUrl);
          //Else we'll load data (that would take some time)
          InputStream ires=(new URL(someUrl)).openStream();    
          ByteArrayOutputStream baos=new ByteArrayOutputStream();
          byte[] raw = new byte[4096];          
          int nBytesRead;
          while ((nBytesRead = ires.read(raw, 0, raw.length))>0)
          baos.write(raw, 0, raw); 
          byte[] downloaded=baos.toByteArray();
          WavAudio curr=new WavAudio(raw);
          cache.put(someUrl,raw);
          return raw;
      }      

      public static void main(String[] args){
          WavAudio wav=WavAudio.loadFromUrl("http://someUrl_1");
          SomePlayer.play(wav); //the first melody is playing
          WavAudio wav=WavAudio.loadFromUrl("http://someUrl_2");
          SomePlayer.play(wav); //the second melody is playing
          //won't be downloaded twice
          WavAudio wav=WavAudio.loadFromUrl("http://someUrl_1");
          SomePlayer.play(wav);
      }
}