Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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 在惰性初始化和一般情况下,重写可以有效地替代if语句吗?_Java_Design Patterns_Inheritance_Overriding_Oop - Fatal编程技术网

Java 在惰性初始化和一般情况下,重写可以有效地替代if语句吗?

Java 在惰性初始化和一般情况下,重写可以有效地替代if语句吗?,java,design-patterns,inheritance,overriding,oop,Java,Design Patterns,Inheritance,Overriding,Oop,我试图模拟下面的抽象类,设计为只启用一个延迟初始化,而不使用逻辑语句。为了简单起见,我忽略了线程安全所必需的同步元素 abstract class Thunk<T> { private boolean initiated = false; private T value; public T get() { if(!initiated) // not using (value == null) {

我试图模拟下面的抽象类,设计为只启用一个延迟初始化,而不使用逻辑语句。为了简单起见,我忽略了线程安全所必需的同步元素

abstract class Thunk<T>
{
    private boolean initiated = false;
    private T value;

    public T get()
    {
        if(!initiated) // not using (value == null)
        {
            value = compute();
            initiated = true;
        }

        return value;
    }

    abstract protected T compute();
}
抽象类Thunk
{
私有布尔值=false;
私人T值;
公共部门得不到
{
如果(!initiated)//未使用(值==null)
{
值=计算();
启动=真;
}
返回值;
}
抽象保护T compute();
}
以下抽象类的实例是否可以被子类黑客攻击以多次初始化同一变量

abstract class Thunk<T>
{
    private T value;
    private Computer<T> computer;

    public Thunk()
    {
        computer = new Computer<T>(this);
    }

    public T get()
    {
        value = computer.getValue();    
        return value;
    }

    abstract protected T compute();

    private class Computer<T> 
    {
        private static final String TAG = "Computer";

        private Thunk<T> thunk;
        private T value;
        private Computer<T> computer;

        public Computer(Thunk<T> thunk)
        {
            Log.d(TAG, "constructed");
            this.thunk = thunk;
            computer = this;
        }

        public T getValue() 
        {
            Log.d(TAG + ".getValue()", "");
            value = computer.computeValue();
            return value;
        }

        protected T computeValue() 
        {
            Log.d(TAG + ".computeValue()", "");
            value = thunk.compute();
            computer = new DumbComputer<T>(thunk, value);
            return value;
        }

        //this is for maximal encapsulation
        private class DumbComputer<T> extends Computer<T>
        {
            private static final String TAG = "DumbComputer";
            private T value;

            public DumbComputer(Thunk<T> thunk, T value) 
            {
                super(thunk);
                Log.d(TAG + ".contructed()", "booki");
                this.value = value; 
            }

            //overriding so that value will be calculated only once.
            @Override
            protected T computeValue() 
            {
                Log.d(TAG + ".computeValue()", "");
                return value;
            }
        }

    }
}
抽象类Thunk
{
私人T值;
专用计算机;
公共Thunk()
{
计算机=新计算机(此);
}
公共部门得不到
{
value=computer.getValue();
返回值;
}
抽象保护T compute();
专用计算机
{
私有静态最终字符串标记=“计算机”;
私人扑通扑通;
私人T值;
专用计算机;
公共计算机(Thunk-Thunk)
{
日志d(标签“已建造”);
this.thunk=thunk;
计算机=这个;
}
公共T getValue()
{
Log.d(标记+”.getValue()“,”);
value=computer.computeValue();
返回值;
}
受保护的T计算值()
{
Log.d(标记+“.computeValue()”,“”);
value=thunk.compute();
计算机=新计算机(thunk,值);
返回值;
}
//这是为了最大限度地封装
私有类计算机扩展计算机
{
私有静态最终字符串标记=“DumbComputer”;
私人T值;
公用计算机(Thunk-Thunk,T值)
{
超级(thunk);
Log.d(TAG+“.constructed()”,“booki”);
这个值=值;
}
//重写,以便仅计算一次值。
@凌驾
受保护的T计算值()
{
Log.d(标记+“.computeValue()”,“”);
返回值;
}
}
}
}

您的第二个示例(可能)没有达到预期效果,因为您每次调用
Thunk.get
时都会创建一台新的
DumbComputer
。您可以实现以下目标(但我认为这不是一个好的设计,我真的不认为与更简单的解决方案相比有什么优势):

抽象类Thunk{
T值;
计算机;
受保护的抽象T doCompute();
专用接口计算机{
计算机getComputer();
T计算();
}
公投(){
//用计算机初始化计算机
计算机=新计算机(){
计算机getComputer(){
//退回一台哑计算机
返回新计算机(){
计算机getComputer(){返回此;}
T compute(){返回值;}
}
}
T compute(){value=doCompute();返回值;}
};
}
公共T getValue(){
tv=computer.compute();computer=computer.getComputer();返回v;
}
}

是,通过重写
get
方法

要解决此问题,可以将
get
转换为
final
方法。这将防止重写并提供类似于单例的行为

请注意,您编写的代码不是线程安全的

通过使方法
同步化
(在你知道你给出了一个问题并且该方法是热点之前,不要担心性能,因为慢正确的代码比快错误的代码好,JVM非常擅长优化锁。如果你发现这个类的某个特定锁太热,你可以使用一些技巧来加速它……但是不要担心这个问题(现在还没有)

还值得指出的是,如果您想要最好的单例惰性init,那么可以使用lazy init的资源持有者内部类模式(不适用于这个类需要的用例。它只用于单例)

更新(以评论不支持格式响应评论)

这样做:

abstract class Thunk<T>
{
    private boolean initiated = false;
    private T value;

    public synchronized final T get()
    {
        if(!initiated) // not using (value == null)
        {
            value = compute();
            initiated = true;
        }

        return value;
    }

    abstract protected T compute();
}
抽象类Thunk
{
私有布尔值=false;
私人T值;
公共同步最终无法获取()
{
如果(!initiated)//未使用(值==null)
{
值=计算();
启动=真;
}
返回值;
}
抽象保护T compute();
}
这是可能工作的最简单的代码。不要梦想尝试“改进”该代码。它可以改进,但改进会因类的使用方式而有所不同,改进的复杂性会隐藏代码试图做的事情。从最简单的可以工作的事情开始,然后继续

保持简单愚蠢

不要解决你还没有解决的问题

public final void f() {
    ...
    X x = ...;
    g(x);
    ...
}

abstract protected void g(X x);
在合同编程中非常有用:

  • 施加行为(主体为f),以及
  • 提供本地上下文(x)
一种行为通常是通过保持一种状态来实现的(比如你的
启动的
)。

因此,是的,这对于延迟评估是很好的。虽然延迟评估可以在字段级别实现,例如通过很少见到的jewel
Future

实现,但实际上不清楚您在问什么。也许可以在代码之外写一个问题的摘要。我可以选择仅同步(锁定)原始computeValue()的内容吗方法,以保存synchr
public final void f() {
    ...
    X x = ...;
    g(x);
    ...
}

abstract protected void g(X x);