หากคุณไม่ต้องการ refactor โค้ดและคุณสามารถใช้ Java 8 ได้คุณสามารถใช้การอ้างอิง Method ได้
การสาธิตอย่างง่ายก่อน (ขออภัยคลาสภายในคงที่)
public class JavaApplication14
{
static class Baz
{
private final int _int;
public Baz(int value){ _int = value; }
public int getInt(){ return _int; }
}
static class Bar
{
private final Baz _baz;
public Bar(Baz baz){ _baz = baz; }
public Baz getBar(){ return _baz; }
}
static class Foo
{
private final Bar _bar;
public Foo(Bar bar){ _bar = bar; }
public Bar getBar(){ return _bar; }
}
static class WSObject
{
private final Foo _foo;
public WSObject(Foo foo){ _foo = foo; }
public Foo getFoo(){ return _foo; }
}
interface Getter<T, R>
{
R get(T value);
}
static class GetterResult<R>
{
public R result;
public int lastIndex;
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
WSObject wsObject = new WSObject(new Foo(new Bar(new Baz(241))));
WSObject wsObjectNull = new WSObject(new Foo(null));
GetterResult<Integer> intResult
= getterChain(wsObject, WSObject::getFoo, Foo::getBar, Bar::getBar, Baz::getInt);
GetterResult<Integer> intResult2
= getterChain(wsObjectNull, WSObject::getFoo, Foo::getBar, Bar::getBar, Baz::getInt);
System.out.println(intResult.result);
System.out.println(intResult.lastIndex);
System.out.println();
System.out.println(intResult2.result);
System.out.println(intResult2.lastIndex);
// TODO code application logic here
}
public static <R, V1, V2, V3, V4> GetterResult<R>
getterChain(V1 value, Getter<V1, V2> g1, Getter<V2, V3> g2, Getter<V3, V4> g3, Getter<V4, R> g4)
{
GetterResult result = new GetterResult<>();
Object tmp = value;
if (tmp == null)
return result;
tmp = g1.get((V1)tmp);
result.lastIndex++;
if (tmp == null)
return result;
tmp = g2.get((V2)tmp);
result.lastIndex++;
if (tmp == null)
return result;
tmp = g3.get((V3)tmp);
result.lastIndex++;
if (tmp == null)
return result;
tmp = g4.get((V4)tmp);
result.lastIndex++;
result.result = (R)tmp;
return result;
}
}
เอาท์พุต
241
4
null
2
อินเทอร์เฟซGetter
เป็นเพียงอินเทอร์เฟซที่ใช้งานได้คุณสามารถใช้สิ่งที่เทียบเท่าได้
GetterResult
class, accessors ถอดออกเพื่อความชัดเจน, ถือผลลัพธ์ของ getter chain, ถ้ามี, หรือดัชนีของ getter ล่าสุดที่เรียก
วิธีการgetterChain
นี้เป็นโค้ดที่เรียบง่ายซึ่งสามารถสร้างขึ้นโดยอัตโนมัติ (หรือด้วยตนเองเมื่อจำเป็น)
ฉันจัดโครงสร้างโค้ดเพื่อให้บล็อกการทำซ้ำนั้นชัดเจนในตัวเอง
นี่ไม่ใช่วิธีแก้ปัญหาที่สมบูรณ์แบบเนื่องจากคุณยังต้องกำหนดหนึ่งโอเวอร์โหลดgetterChain
ต่อจำนวนผู้ได้รับ
ฉันจะ refactor รหัสแทน แต่ถ้าทำไม่ได้และคุณพบว่าตัวเองใช้โซ่ยาว ๆ บ่อยครั้งคุณอาจพิจารณาสร้างคลาสที่มีโอเวอร์โหลดซึ่งใช้เวลาตั้งแต่ 2 ถึง 10 ขึ้นไป
null
ตรวจสอบมากนักเนื่องจากwsObject.getFoo().getBar().getBaz().getInt()
เป็นกลิ่นรหัสอยู่แล้ว อ่านว่า"Law of Demeter"คืออะไรและต้องการปรับรหัสของคุณให้สอดคล้องกัน แล้วปัญหาเรื่องnull
เช็คก็จะหมดไปเช่นกัน และคิดเกี่ยวกับการใช้Optional
.