The Builder Pattern可以作为一个依赖inector来消除初始化过程中的死锁。由于Chicken 类依赖于一个接口(@987654325@),该接口本身无法实例化,因此可以应用this question 中提到的模式。
这个例子有3个版本的介绍。第一个更简单,但它也提供了访问半完成的Chicken 类的可能性。在每个版本中,都以复杂性为代价消除了越来越多的歧义。
public class MyClass {
/**
* Handles eggs
* */
public static class Chicken{
private Egg[] eggs;
private Chicken(){}
private void setEggs(Egg... eggs_){ eggs = eggs_; }
public void accept_signal(String message){ /* ... */ }
public static class Builder{
Chicken momma;
public Builder(){
momma = new Chicken();
}
public Chicken build(Egg... eggs){
momma.setEggs(eggs);
return momma;
}
public Chicken get(){
return momma;
}
}
}
/**
* Signals when its ready to hatch
* */
public static abstract class Egg{
private final Chicken parent;
public Egg(Chicken parent_){
parent = parent_;
}
public void hatch(){
parent.accept_signal("chirp chirp");
}
}
/**
* The resulting children to be handled
* */
public static class YellowChick extends Egg{
public YellowChick(Chicken parent_){
super(parent_);
}
}
public static class BrownChick extends Egg{
public BrownChick(Chicken parent_){
super(parent_);
}
}
public static class UglyDuckling extends Egg{
public UglyDuckling(Chicken parent_){
super(parent_);
}
}
public static void main (String[] args){
Chicken.Builder mommaBuilder = new Chicken.Builder();
Chicken momma = mommaBuilder.build(
new YellowChick(mommaBuilder.get()),
new BrownChick(mommaBuilder.get()),
new UglyDuckling(mommaBuilder.get())
);
System.out.println("Success!");
}
}
另一个版本旨在使用来自this question 的解决方案将访问半完成的Chicken 类仅限于相关类(Egg 的子类):
import java.util.Objects;
public class MyClass {
/**
* Handles eggs
* */
public static class Chicken{
private Egg[] eggs;
private Chicken(){}
private void setEggs(Egg... eggs_){ eggs = eggs_; }
public void accept_signal(String message){
/* ... */
}
public static class Builder{
Chicken momma;
public Builder(){
momma = new Chicken();
}
public Chicken build(Egg... eggs){
momma.setEggs(eggs);
return momma;
}
public Chicken get(Egg.Token token){
Objects.requireNonNull(token, "Only call this in function from a valid Builder");
return momma;
}
}
}
/**
* Signals when its ready to hatch
* */
public static abstract class Egg{
public static class Token{ private Token(){}}
private final Chicken parent;
public Egg(Chicken.Builder builder){
parent = builder.get(new Token());
}
public void hatch(){
parent.accept_signal("chirp chirp");
}
}
/**
* The resulting children to be handled
* */
public static class YellowChick extends Egg{
public YellowChick(Chicken.Builder builder){
super(builder);
}
}
public static class BrownChick extends Egg{
public BrownChick(Chicken.Builder builder){
super(builder);
}
}
public static class UglyDuckling extends Egg{
public UglyDuckling(Chicken.Builder builder){
super(builder);
}
}
public static void main (String[] args){
Chicken.Builder mommaBuilder = new Chicken.Builder();
Chicken momma = mommaBuilder.build(
new YellowChick(mommaBuilder),
new BrownChick(mommaBuilder),
new UglyDuckling(mommaBuilder)
);
System.out.println("Success!");
}
}
尽管这仍然允许使用不同的构建器实例构建每个小鸡,并且仍然添加到 Chicken 下。为了解决这个问题,只要 Chicken 有来自另一个巢穴的 Chick (Chicken.Builder),就会引发异常:
import java.util.HashMap;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
public class MyClass {
/**
* Handles eggs
* */
public static class Chicken{
private Egg[] eggs;
private Chicken(){}
private void setEggs(Egg... eggs_){ eggs = eggs_; }
public void accept_signal(String message){
/* ... */
}
public static class Builder{
Chicken momma;
HashSet<Integer> accessors;
public Builder(){
momma = new Chicken();
accessors = new HashSet<>();
}
public Chicken build(Egg... eggs){
for(Egg egg : eggs){
if(!accessors.contains(egg.getToken()))
throw new IllegalStateException("Unable to accept step-chick!");
}
momma.setEggs(eggs);
return momma;
}
public Chicken get(Egg.Token token){
Objects.requireNonNull(token, "Only call this in function from a valid Builder");
accessors.add(token.hashCode());
return momma;
}
}
}
/**
* Signals when its ready to hatch
* */
public static abstract class Egg{
public static class Token{ private Token(){}}
private final Chicken parent;
private final Token token = new Token();
public Egg(Chicken.Builder builder){
parent = builder.get(token);
}
public int getToken(){return token.hashCode();}
public void hatch(){
parent.accept_signal("chirp chirp");
}
}
/**
* The resulting children to be handled
* */
public static class YellowChick extends Egg{
public YellowChick(Chicken.Builder builder){
super(builder);
}
}
public static class BrownChick extends Egg{
public BrownChick(Chicken.Builder builder){
super(builder);
}
}
public static class UglyDuckling extends Egg{
public UglyDuckling(Chicken.Builder builder){
super(builder);
}
}
public static void main (String[] args){
Chicken.Builder mommaBuilder = new Chicken.Builder();
Chicken momma = mommaBuilder.build(
new YellowChick(mommaBuilder),
new BrownChick(mommaBuilder),
new UglyDuckling(mommaBuilder)
);
System.out.println("Success!");
}
}