如果我有这个课程:
public interface IBinaryCalculator{
double addition(double numb1, double numb2);
}
public class BinaryCalculator implements IBinaryCalculator{
double addition(double numb1, double numb2){
return numb1+numb2;
}
}
好的,这个方法应该是静态的,但是我在这里有一个接口。单身是唯一的答案,只是在课堂上为BinaryCalc?假设我构建了10,000个BinaryCalculator,它只有方法,它对性能有影响,还是应该使用单例。
答案 0 :(得分:1)
这个特定类中没有任何东西不能“静止”。
当一个类实例可能具有不同的状态数据时,那么您将需要单个对象。
“Singleton”是一回事(原谅双关语; - ))。
“静态”是另一回事。
可伸缩性是另一个独立的问题。
底线:如果你需要某个东西作为一个对象,那么把它变成一个对象。如果一个方法永远不需要引用实例数据 - 无论如何。如果你愿意,可以自己解决问题,并将其作为一种静态方法。
... IMHO
答案 1 :(得分:1)
我无法完全确定,但您似乎过分担心与创建给定对象的许多实例相关的性能问题。
恕我直言,你应该首先担心设计,如果这样的事情成为问题,你可以担心性能。老实说,你的班级看起来不像是你将有一百万个物品在堆里游泳的类。您的界面就是所谓的SAM类型(单一抽象方法)。 JDK本身就有很多这样的例子。例如,java.util.Comparator和java.lang.Comparable是两个很好的例子。
如果将方法定义为静态,则必须基于您的设计,而不是基于其执行的任务的功能或简单性。您可能比其他任何人都更了解您的设计,本论坛的开发人员可以帮助您提出好的想法或挑战您当前的设计,这可能有助于改善您已有的设计。
您提到的单例模式旨在阻止创建超过预定义数量的给定类的实例,通常它们将其限制为单个实例。在你的设计中,为什么你想做这样的事情并不明显,但是担心与实例数相关的性能并不是最好的理由。
在寻找简化设计的方法时,如果计划使用不同类型的计算器,可能需要static factory method类您可以在其中放置所有SAM类型的实现:
public class Calculators {
public static BinaryCalculator getBasicCalculator(){
return new BinaryCalculator() {
@Override
public double addition(double numb1, double numb2) {
return numb1 + numb2;
}
};
}
public static BinaryCalculator getSofisticatedCalculator(){
return new BinaryCalculator() {
@Override
public double addition(double numb1, double numb2) {
//do any other sofisticated calculation
return numb1 + numb2;
}
};
}
}
然后你可以这样做:
public static void main(String[] args) {
BinaryCalculator simple = Calculators.getBasicCalculator();
BinaryCalculator complex = Calculators.getSofisticatedCalculator();
double result;
result = simple.addition(10,11);
result = complex.addition(10,11);
}
此外,如果您被允许进行实验,您可能想试试JDK 8 Lambda Preview,您可以将计算器的实现编写为lamdba表达式。
BinaryCalculator simple = (num1, num2) -> num1 + num2;
甚至在方法中内联,例如
public class Pair {
private final double a;
private final double b;
public Pair(double a, double b){
this.a = a;
this.b = b;
}
public double calculateWith(BinaryCalculator calculator){
return calculator.addition(a,b);
}
}
然后你可以简单地为你的SAM类型提供一个lambda实现,如下所示:
Pair p = new Pair(10,11);
double result = p.calculateWith( (num1, num2) -> num1 + num2 );
System.out.println(result);
当然,这只是JDK 8的预览,但是,如果您被允许尝试最新功能,那么这将是一个非常酷的解决方案: - )
答案 2 :(得分:0)
几个问题,几个答案。
答案 3 :(得分:0)
不要'做:
10,000 new BinaryCalculator().addition(42,24);
执行:
BinaryCalculator bc = new BinaryCalculator();
10,000 bc.addition(42,24);
如果您使用:
MemoryMXBean mBean = ManagementFactoryHelper.getMemoryMXBean();
mBean.getHeapMemoryUsage().getUsed()
在一个单独的测试中,您应该看到第一个示例中的getUsed()增长和收缩,以及第二个示例中的稳定使用。您还可以使用getUsed()来了解堆耗尽和GC的速度。
答案 4 :(得分:0)
单个类实例使用的内存取决于您使用的JVM,在某些情况下取决于其他内容。但是对象的标题通常占用8到16个字节。根据对对象的处理,也可以有其他隐藏状态; e.g。
但是,这可能对您的应用程序的性能没有任何可衡量的影响。