ใน Java 8 นั้นมี feature ที่น่าสนใจมากมาย
แน่นอนว่า ความสามารถต่าง ๆ นั้นถูกสร้างขึ้นมา
เพื่อลดปัญหาที่เกิดจากตัวภาษา เช่น
- Lambda
- Functional Interface
- Default method ใน interface
เริ่มต้นจากแนวคิดที่ได้จากหนังสือ Design Pattern
- เน้นไปที่ interface เป็นหลัก ไม่ใช่เน้นที่ implementation นะ
- Composition over Inheritance
ตัวอย่างแรกคือ การบวกลบคูณหาร
เพื่อเป็นการทดสอบความเข้าใจในความสามารถของภาษา ถ้าเราใช้แนวคิดจากข้างต้น สามารถสร้าง interface ชื่อว่า Calculator ได้ดังนี้ [gist id="abde422c8c64db8f75902dc73f1468d5" file="1.java"] จากนั้นทำการสร้างบวกลบคูณหาร จาก interface นี้ ด้วย Lambda แบบสั้น ๆ นิดหน่อย ดังนี้ [gist id="abde422c8c64db8f75902dc73f1468d5" file="2.java"] รูปแบบของภาษาจะแปลก ๆ หน่อยแต่ก็ต้องเรียนรู้กันนะตัวอย่างต่อมา น่าจะทำให้เข้าใจเรื่อง Design Pattern มากยิ่งขึ้น
เป็นตัวอย่าง code ที่เจอมาก ๆ ใน code คือ Logger !! จะอธิบายแบบ step-by-step เพื่อให้เห็นปัญหา และ แนวทางในการแก้ไขปัญหา ทั้ง inheritance ทั้ง composition ทั้ง Functional interface ใน Java 8 มาเริ่มกันเลยขั้นตอนที่ 1 สร้าง Logger อย่างง่ายมาใช้งานก่อน
แน่นอนว่า เริ่มจาก interface นั่นแหละ และทำการแสดง log message ออกไปที่ console สามารถเขียน code ได้ดังนี้ [gist id="abde422c8c64db8f75902dc73f1468d5" file="3.java"]ขั้นตอนที่ 2 ถ้าต้องการใส่ filter ใน logger จะต้องทำอย่างไร ?
[gist id="abde422c8c64db8f75902dc73f1468d5" file="4.java"] แน่นอนว่า เราต้องการใส่ filter ได้หลายรูปแบบตามที่ต้องการ ดังนั้นสิ่งที่สำคัญมาก ๆ คือ การคิด (Thinking before Coding) ว่าจะออกแบบ จะสร้างออกมาอย่างไรดี ? โดยแนวคิดที่ผมพอจะคิดได้เป็นดังนี้แนวคิดที่ 1 คือ Inheritance
ถ้าเทียบใน Design pattern คือ Template method pattern นั่นเอง ดังนั้นเราต้องสร้าง abstract class ขึ้นมา เพื่อกำหนด template ของ Logger ที่มี filter สามารถเขียน code ได้ดังนี้ [gist id="abde422c8c64db8f75902dc73f1468d5" file="5.java"] ดังนั้นใครที่ต้องการใช้งานก็ให้สร้าง class ที่ extend จาก abstract class นี้ซะ ตัวอย่างคือ TestLogger จะทำการแสดง log message เฉพาะที่ขึ้นต้นด้วยคำว่า Test เท่านั้น สามารถเขียน code ได้ดังนี้ [gist id="abde422c8c64db8f75902dc73f1468d5" file="6.java"]แนวคิดที่ 2 คือ Composition
เป็นแนวคิดที่หนังสือ Design pattern แนะนำให้คิดและออกแบบก่อน เนื่องจากเป็นวิธีการที่เรียบง่ายกว่า โดยทำการสร้าง class สำหรับรวม Logger และ Filter ไว้ ด้วยการ injection dependency ต่าง ๆ เข้าไป จากตัวอย่างเป็นการใช้ Constructor Injection ดังนี้ [gist id="abde422c8c64db8f75902dc73f1468d5" file="7.java"] การใช้งานก็ไม่ยาก [gist id="abde422c8c64db8f75902dc73f1468d5" file="8.java"] มาถึงตรงนี้น่าจะทำให้เห็นว่า ระหว่างแนวคิด Composition และ Inheritance นั้นเป็นอย่างไร ? อะไรยากกว่า ? อะไรง่ายกว่า ? ซึ่งมันขึ้นอยู่กับบริบทหลาย ๆ อย่างนะครับ จากตัวอย่างมันเอื้อให้แนวคิด composition เท่านั้นเองแนวคิดที่ 3 ใช้ความสามารถของ Java 8 คือ default method ใน interface
เป็นวิธีการที่ Java Developer น่าจะต้องรู้จักไว้บ้างนะ ถ้ายังไม่รู้ก็รู้ไว้ซะ จะใช้งานหรือไม่ ก็ไม่เสียหายอะไร สิ่งที่ต้องการให้เห็นคือ ตัวภาษา Java พยายามจะแก้ไขปัญหาของภาษามันเอง โดยจากตัวอย่างนี้ เราไม่ต้องสร้าง class อะไรมาเลย ใช้เพียง default method ใน interface กับความสามารถของ Functional Interface เลย เขียน code ได้ดังนี้ [gist id="abde422c8c64db8f75902dc73f1468d5" file="9.java"] ส่วนการใช้งานก็เหมือนกับ composition นั่นเอง เห็นไหมว่า วิธีการนี้ช่วยลดและแก้ไขปัญหาไปพอสมควร ทำให้เราเห็นวิธีการแก้ไขปัญหาอีกมุมนะครับคำถามคือ จะใช้แบบไหนดี ?
คำตอบคือ ทีมคุณไง ว่าสามารถดูแลรักษา code แบบไหนได้ดี และที่สำคัญเขียนชุดการทดสอบคลุมหรือยัง ? จะได้ไม่กลัวในการเปลี่ยนแปลงเป้าหมายหลัก ๆ ของการแบ่งปันครั้งนี้เพื่อ
- เข้าใจ feature ต่าง ๆ ใน Java 8 ว่ามีที่มาอย่างไร และช่วยอะไรบ้าง ?
- เข้าใจว่าปัญหาคืออะไร และมีความพยายามแก้ไขอย่างไร
- Design pattern คือสิ่งที่บอกปัญหาของภาษานั้น ๆ
- Design pattern เกิดจากปัญหาที่เกิดขึ้นซ้ำ ๆ จึงมีคนคิด solution ไว้ให้ คำถามคือ คุณเห็นปัญหาหรือยัง ? ถ้ายังอย่างเพิ่งนำมาใช้
สำหรับ Java Developer วันนี้คุณรู้จัก feature ต่าง ๆ ใน Java 8 แล้วหรือยัง ?สำหรับ source code ตัวอย่างอยู่ที่ Github:: Up1:: Demo โดย slide อยู่ที่นี่ [slideshare id=69918048&doc=sck-design-pattern-161207151218&w=640&h=480]