刚开始想要通过工厂模式来实现,但发现为了创建不同的Outbound实例需要强制规定Outbound的实现者去实现一个public static Object getInstance(),虽然JDK1.8提供了Interface static,但实现者却不能Override。最终有了下面的解决办法:

传统的Singleton pattern模式:

1
2
3
4
5
6
7
8
9
10
11
12
public class Socks5{
private static Socks5 socks5 = null;
private Socks5(){
}

public static Socks5 getInstance(){
if(socks5 == null){
return socks5 = new Socks5();
}
return socks5;
}
}

但是我想实现一个对象的创建全部由Socks5的编写者来控制的模式,StackOverflow上面没找到答案,所以有了下面写的样子。

一个仿Singleton pattern模式

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface Inbound {
default Inbound getInstance(){
try {
return this.getClass().getConstructor().newInstance();
} catch (InstantiationException
| IllegalAccessException
| InvocationTargetException
| NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Socks5 implements Inbound {
private static Socks5 socks5 = null;

@Override
public Inbound getInstance(){
if(socks5 == null){
socks5 = new Socks5();
}
return socks5;
}

public static void main(String[] argv){
Inbound inbound = new Socks5();
System.out.println(inbound.getClass().getName());
Inbound in1 = inbound.getInstance();
Inbound in2 = inbound.getInstance();
System.out.println(in1 == in2);
}
}

Result:

1
2
Socks5
true

通过这种方式可以让对象的创建由继承了Inbound接口的编写者来负责,但是调用者必须保证只能使用new来创建一个Socks5的实例。

还有一种方法可以强制调用者只使用一次new

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Socks5 implements Inbound {
private static Socks5 socks5 = null;
private static boolean created = false;
public Socks5() throws Exception {
if(created){
throw new Exception("cannot create");
}
created = true;
}

private Socks5(int a ){
}

@Override
public Inbound getInstance(){
if(socks5 == null){
try {
socks5 = new Socks5(1);
} catch (Exception e) {
e.printStackTrace();
}
}
return socks5;
}

public static void main(String[] argv) throws Exception {
Inbound inbound = new Socks5();
Inbound inbound2 = new Socks5();
System.out.println(inbound.getClass().getName());
Inbound in1 = inbound.getInstance();
Inbound in2 = inbound.getInstance();
System.out.println(in1 == in2);
}
}

Result:

1
2
3
Exception in thread "main" java.lang.Exception: cannot create
at Socks5.<init>(Socks5.java:6)
at Socks5.main(Socks5.java:29)

通过构造函数抛出异常来强行禁止调用者多次使用new创建。缺点是new的时候需要try catch,不美观。

我本身想要实现让继承自Inbound接口的编写者来自己控制对象的创建,这样我只负责将参数传递给对象也不管是否是同一个对象

这样我会保证new操作符只是用一次,所以第一种方法很整洁。