以下是该方案:
public class A {
public A {}
void doSomething() {
// do something here...
}
}
现在,该类已设置,您可以在其中创建多个实例。但我也看到需要将类限制为只有一个实例,即Singleton类。
问题是我不确定如何完成两个目标的设计:多个实例和一个实例。在一堂课中听起来不太可能。我想我需要使用派生类,抽象类,接口,其他东西或某种组合。
我应该将A类创建为基类并创建一个作为单例类的派生类吗?
答案 0 :(得分:3)
当然,首先应该始终质疑使用单身人士的必要性。但有时,它们只是解决某些问题的务实方式。
如果是这样,首先要理解的是:没有解决方案可以强制执行"您的要求并防止误用,但这是一个"模式"通过转变"意图"这有很大帮助。进入"有意义的"代码:
首先,我有一个表示功能的界面:
interface WhateverService { void foo() }
然后,我有一些想法:
class WhateverServiceImpl implements WhateverService {
@Override
void foo() { .... }
现在,如果我需要以单身形式存在,我会
enum WhateverServiceProvider implements WhateverService {
INSTANCE;
private final WhateverService impl = new WhateverServiceImpl();
@Override
void foo() { impl.foo() }
最后,一些客户端代码可以执行:
WhateverService service = WhateverServiceProvider.INSTANCE;
service.foo()
(但当然,你可能不想直接分配服务对象,但你可以在这里使用依赖注入)
这样的架构可以为您提供:
更新 - 关于线程安全:
我不确定你的意思是什么"单身概念"。
但是我们可以这样说:当你使用这样的枚举时,保证有一个完全实例化一个INSTANCE对象,Java语言保证这一点。但是:如果有几个线程转向枚举,并且并行调用foo()......你仍然在处理围绕这些场景的所有潜在问题。所以,是的,enum"创造"是线程安全的;但是你的代码正在做什么......取决于你。那么锁定或其他任何有意义的东西。
答案 1 :(得分:2)
我想你应该看看这个问题: Can a constructor in Java be private?
这里描述的Builder模式可能有一些有趣的解决方案:
// This is the class that will be produced by the builder
public class NameOfClassBeingCreated {
// ...
// This is the builder object
public static class Builder {
// ...
// Each builder has at least one "setter" function for choosing the
// various different configuration options. These setters are used
// to choose each of the various pieces of configuration independently.
// It is pretty typical for these setter functions to return the builder
// object, itself, so that the invocations can be chained together as in:
//
// return NameOfClassBeingCreated
// .newBuilder()
// .setOption1(option1)
// .setOption3(option3)
// .build();
//
// Note that any subset (or none) of these setters may actually be invoked
// when code uses the builer to construct the object in question.
public Builder setOption1(Option1Type option1) {
// ...
return this;
}
public Builder setOption2(Option2Type option2) {
// ...
return this;
}
// ...
public Builder setOptionN(OptionNType optionN) {
// ...
return this;
}
// ...
// Every builder must have a method that builds the object.
public NameOfClassBeingCreated build() {
// ...
}
// The Builder is typically not constructible directly
// in order to force construction through "newBuilder".
// See the documentation of "newBuilder" for an explanation.
private Builder() {}
}
// Constructs an instance of the builder object. This could
// take parameters if a subset of the parameters are required.
// This method is used instead of using "new Builder()" to make
// the interface for using this less awkward in the presence
// of method chaining. E.g., doing "(new Foo.Builder()).build()"
// is a little more awkward than "Foo.newBuilder().build()".
public static Builder newBuilder() {
return new Builder();
}
// ...
// There is typically just one constructor for the class being
// constructed that is private so that it may only be invoked
// by the Builder's "build()" function. The use of the builder
// allows for the class's actual constructor to be simplified.
private NameOfClassBeingCreated(
Option1Type option1,
Option2Type option2,
// ...
OptionNType optionN) {
// ...
}
}
链接供参考: https://www.michaelsafyan.com/tech/design/patterns/builder
答案 2 :(得分:1)
我不确定这是你在找什么,但你可以使用工厂模式。创建2个工厂,一个将始终返回相同的单例,而另一个将每次创建一个新的A对象。
Factory singletonFactory = new SingetonFactory();
Factory prototypeFactory = new PrototypeFactory();
A a = singletonFactory.createA();
A b = singletonFactory.createA();
System.out.println(a == b); // true
A c = prototypeFactory.createA();
A d = prototypeFactory.createA();
System.out.println(c == d); // false
class A {
private A() {}
void doSomething() { /* do something here... */}
}
interface Factory {
A createA();
}
class SingetonFactory implements Factory {
private final A singleton = new A();
public A createA() {
return singleton;
}
}
class PrototypeFactory implements Factory {
public A createA() {
return new A();
}
}