Java 为什么不';是否使用静态变量来共享子类的对象?

Java 为什么不';是否使用静态变量来共享子类的对象?,java,oop,design-patterns,Java,Oop,Design Patterns,我的问题有点长。 我正在学习抽象工厂模式 我有一个抽象工厂的抽象类。 我想分享混凝土工厂所需的“资源”。 因此,我只是将AbstractFactory中的变量设置为静态变量 public class AbstractFactory{ private static Vector vector = new Vector(); protected Vector void getVector() { return vector; } protected

我的问题有点长。 我正在学习抽象工厂模式

我有一个抽象工厂的抽象类。 我想分享混凝土工厂所需的“资源”。 因此,我只是将AbstractFactory中的变量设置为静态变量

public class AbstractFactory{
    private static Vector vector = new Vector();

    protected Vector void getVector() {
        return vector;
    }

    protected void setVector(Vector v){
        this.vector = v;
    }

    public abstract Circle createCircle();
}
其子类将如下所示:

public class ConcreteFactory extends AbstractFactory{
    public ConcreteFactory(){
        super();
    }

    public Circle createCircle(){
        Circle circle = new Circle();
        getVector().add(circle);
        return circle;
    }
}
public class AbstractFactory{
    private Vector vector;

    protected Vector void getVector() {
        return vector;
    }

    protected void setVector(Vector v){
        this.vector = v;
    }

    public abstract Circle createCircle();
}

public class ConcreteFactory extends AbstractFactory{
    public ConcreteFactory(Vector v){
        super();
        setVector(v);
    }

    public Circle createCircle(){
        Circle circle = new Circle();
        getVector().add(circle);
        return circle;
    }
}
但是,我的老师说我不应该使用静态对象实例 因为静态变量通常用于某些常量。

因此,对于向量 ,当我实例化混凝土工厂时,我从外部传递向量

因此,我的课程的新设计将如下所示:

public class ConcreteFactory extends AbstractFactory{
    public ConcreteFactory(){
        super();
    }

    public Circle createCircle(){
        Circle circle = new Circle();
        getVector().add(circle);
        return circle;
    }
}
public class AbstractFactory{
    private Vector vector;

    protected Vector void getVector() {
        return vector;
    }

    protected void setVector(Vector v){
        this.vector = v;
    }

    public abstract Circle createCircle();
}

public class ConcreteFactory extends AbstractFactory{
    public ConcreteFactory(Vector v){
        super();
        setVector(v);
    }

    public Circle createCircle(){
        Circle circle = new Circle();
        getVector().add(circle);
        return circle;
    }
}
**

我的问题是:为什么我不应该使用静态变量来共享对象? **

在混凝土工厂之间共享资源将更容易,而无需传递向量
当我创建一个混凝土工厂的实例时。

静态
属性不应该这样使用。
static
s是在运行时只可用一次的东西。
在您的例子中,这意味着
抽象工厂派生的所有工厂将共享这个向量

请参见此示例:

ConcreteFactory a = new ConcreteFactory();
ConcreteFactory b = new ConcreteFactory();
a.createCircle();
b.createCircle();
两个对象
a
b
现在在向量中都有两个条目,因为它们共享相同的静态向量

我也认为

protected void setVector(Vector v){
    this.vector = v;
}
是非法的,因为
vector
不是工厂实例的属性,而是工厂本身的属性

除此之外,这只是一种糟糕、容易出错(试着在更大范围内调试它)和丑陋的编码风格


只要相信你的老师——他是对的;)

静态
属性不应该这样使用。
static
s是在运行时只可用一次的东西。
在您的例子中,这意味着
抽象工厂派生的所有工厂将共享这个向量

请参见此示例:

ConcreteFactory a = new ConcreteFactory();
ConcreteFactory b = new ConcreteFactory();
a.createCircle();
b.createCircle();
两个对象
a
b
现在在向量中都有两个条目,因为它们共享相同的静态向量

我也认为

protected void setVector(Vector v){
    this.vector = v;
}
是非法的,因为
vector
不是工厂实例的属性,而是工厂本身的属性

除此之外,这只是一种糟糕、容易出错(试着在更大范围内调试它)和丑陋的编码风格


只要相信你的老师——他是对的;)

有时候,今天让你的生活更轻松的事情会让你的生活变得越来越困难

一些例子:你并不总是知道你的类将被使用的环境。也许工厂的不同实例最终会被不同的类装入器装入(这在web应用程序中经常发生)。这样使用静态实例变量可能会导致完全不可预测的行为。静态变量几乎总是一个坏主意

也就是说,我认为你在课堂上真正想做的是:

public class AbstractFactory{
    private final Vector vector;

    protected AbstractFactory(Vector vector){
        this.vector = vector;
    }

    protected Vector void getVector() {
        return vector;
    }

    public abstract Circle createCircle();
}


在实例变量上使用final是解决这类问题的一个好办法,它可以防止您在代码的其他地方意外更改变量。但这是可选的。我所做的关键更改是将vector添加到抽象基类的构造函数中,然后将它从超类传入。

有时候,今天让您的生活更轻松的事情会让它变得越来越困难

一些例子:你并不总是知道你的类将被使用的环境。也许工厂的不同实例最终会被不同的类装入器装入(这在web应用程序中经常发生)。这样使用静态实例变量可能会导致完全不可预测的行为。静态变量几乎总是一个坏主意

也就是说,我认为你在课堂上真正想做的是:

public class AbstractFactory{
    private final Vector vector;

    protected AbstractFactory(Vector vector){
        this.vector = vector;
    }

    protected Vector void getVector() {
        return vector;
    }

    public abstract Circle createCircle();
}

在实例变量上使用final是解决这类问题的一个好办法,它可以防止您在代码的其他地方意外更改变量。但这是可选的。我所做的关键更改是将vector添加到抽象基类的构造函数中,然后将其从超类传入。

静态最终变量有时用作常量的事实不应阻止您在其服务最好的位置使用相同的机制(logger是我能给出的唯一其他示例)

但是,当外部世界没有隐式组件耦合时,它总是好的。若你们将vector定义为一个静态变量,那个么用户就不可能让你们的工厂基于上下文,彼此独立。如果将向量作为工厂的参数,那么由工厂创建者(现在通常是Spring上下文加载器)定义哪些工厂共享向量,哪些工厂不共享向量

在您的案例中,将vector作为参数传递的另一个原因与单元测试方面有关。如果你的类被设计成从外部获取向量,你可以模拟它并更彻底地测试你的类。

静态最终变量有时被用作常量这一事实不应该阻止你在它服务最好的地方使用相同的机制(logger是我能给出的唯一其他例子)

但是,当外部世界没有隐式组件耦合时,它总是好的。若你们将vector定义为一个静态变量,那个么用户就不可能让你们的工厂基于上下文,彼此独立。如果将向量作为工厂的参数,那么由工厂创建者(现在通常是Spring上下文加载器)定义哪些工厂共享向量,哪些工厂不共享向量

另一个