Saladpuk.com
🏆 เนื้อหาหลัก
🏆 เนื้อหาหลัก
  • 💖สลัดผัก
  • 📰มีอะไรใหม่บ้าง
    • 2020
      • 2020-11
      • 2020-10
      • 2020-09
      • 2020-08
      • 2020-03
      • 2020-02
      • 2020-01
    • 2019
      • 2019-12
      • 2019-11
      • 2019-10
      • 2019-09
      • 2019-08
  • 🤔อ่านเรื่องไรดี ?
  • มือใหม่หัดเขียนโค้ด
    • 👶เขียนโค้ดด้วยภาษา C#
      • เกิดมาไม่เคยเขียนโค้ดมาก่อนเบย
      • 👶พื้นฐาน
        • 1.โปรแกรมที่ต้องลง
        • 2.โครงสร้างของโค้ด
        • 3.ชนิดของข้อมูล
        • 4.การสร้างตัวแปร
        • 5.คำสั่งพื้นฐาน
        • 6.การแปลงข้อมูล
        • 7.การเปรียบเทียบค่า
        • 8.การตัดสินใจด้วย IF statements
        • 9.การตัดสินใจด้วย Switch statements
        • 10.การทำงานซ้ำๆด้วย While
        • 11.การทำงานซ้ำๆด้วย Do While
        • 12.การทำงานซ้ำๆด้วย For
        • 13.การแก้โจทย์จากรูป
        • 14.มารู้จักกับ Array กัน
      • 🧑ระดับกลาง
        • 15.Value type vs Reference type
        • 16.ลดงานซ้ำๆด้วย Method
        • 17.มารู้จักกับ Class & Field กัน
        • 18.มารู้จักกับ Constructor กันบ้าง
        • 19.มาเขียน Method ใน Class กัน
        • 20.มารู้จักกับ Property กัน
        • 21.ลองใช้คลาสแบบจริงจังบ้าง
        • 22.การสืบทอด Inheritance
        • 23.Polymorphism
        • 24.Abstract Class
        • 25.Interface
        • 26.Namespace
        • 27.Enum
        • 28.Exception handler
        • 29.ลงลึกกับ string
        • 30.StringBuilder เพื่อนคู่ string
      • 👨⏳ระดับสูง
        • Generic
        • Delegates
        • Action & Func
        • Lambda expression
        • LINQ
        • พระคัมภีร์การใช้คำสั่ง LINQ
      • 💡Tips
        • 💡C# version 8.0
        • 💡Boxing & Unboxing
    • 👶Algorithm
      • 👾Algorithm Big-O
      • 👽Algorithm P & NP
    • 👦OOP
      • 💖Abstraction
      • 💖Encapsulation
      • 🏆Abstraction & Encapsulation
      • 💖Inheritance
      • 💖Polymorphism
      • 🏆Inheritance & Polymorphism
      • 📝ลองเขียน OOP ดูดิ๊
      • 👑OOP + Power of Design
      • 🥰เทคนิคในการออกแบบ
    • 👶บทสรุปฐานข้อมูล
      • เก็บรูปในฐานข้อมูล
      • Database indexing
      • การลบข้อมูล
    • 👦Communication Patterns
    • 👦Design Patterns
      • 🤰Creational Patterns
        • 🏭Factory Method
        • 🏭Abstract Factory
        • ☝️ Singleton Pattern
        • 🏗️ Builder Pattern
        • 🎎Prototype Pattern
      • 🧱Structural Patterns
        • 🔌Adapter Pattern
        • 📪Proxy Pattern
  • Puzzle
    • 🧠Challenges
      • 🐴Google ม้า 25 ตัว
      • 🌉Amazon เสา 2 ต้น
      • 🥇ทองเก๊
      • 💊ยาต้านโควิด
      • 🎩CP หมวก 5 ใบ
      • 🧓Einstein's Riddle 01
  • พื้นฐานที่ควรต้องรู้
    • 🐳Docker
      • 📦Docker Containers
      • 🃏Docker Exercise 01
      • 🛠️ Docker Tools
      • 🗃️ Docker Registry
      • 🖼️ Container Image
      • 📢Docker Push
      • 🔄WSL
    • 👶Clean Code
      • 🧓Uncle Bob - Clean Code
      • 🧓Uncle Bob - Comments
      • 🧓Uncle Bob - Naming
      • 🧓Uncle Bob - Mindset
      • 🧓Uncle Bob - TDD
    • 👶Code Smells
    • 👶สิ่งที่คนเขียนโค้ดมักเข้าใจผิด
    • 👶AI พื้นฐาน
    • 👶Git พื้นฐาน
      • Git branching strategy
    • 👶Cloud พื้นฐาน
    • 👶UML พื้นฐาน
      • Activity Diagram
      • Class Diagram
      • Sequence Diagram
      • Use case Diagram
      • บทสรุปการใช้ UML
    • 👶Data Scientist
      • การเลือก Algorithms ให้ AI (1/5)
      • การเตรียมข้อมูลให้ AI (2/5)
      • หลักการตั้งคำถามให้ AI (3/5)
      • แฉความลับของ AI Model (4/5)
      • หัดเขียน AI จาก AI ของคนอื่น (5/5)
    • 👶DevOps พื้นฐาน
    • 👶Docker ขั้นพื้นฐาน
      • Image and Container
      • แชร์ Docker Image ที่สร้างไว้
    • 👶Microservices พื้นฐาน
      • Microservices ที่ดีมีลักษณะยังไง
      • Microservices Tips
      • จาก Monolith สู่ Microservices
    • 👶ความรู้พื้นฐานในการทำเว็บ
    • 👦Bottlenecks of Software
      • หัวใจที่สำคัญที่สุดของฐานข้อมูล
    • 👦Agile Methodology
      • Agile in a Nutshell
      • Software Development Life Cycle
      • Code Review
    • 👦Security พื้นฐาน
      • การเก็บรหัสผ่านที่ถูกต้อง
      • Security in actions
        • Hash function
      • Security Principles
      • 😎The Matrix 1
      • 😎The Matrix 2
      • HTTPS in a nutshell
    • 👦SOLID Design Principles
      • มารู้จักกับ SOLID กันดีกว่า
      • Single-Responsibility Principle
      • Open/Closed Principle
      • Liskov Substitution Principle
      • Interface Segregation Principle
      • Dependency-Inversion Principle
  • Cloud Computing
    • 👶Microsoft Azure 101
      • สมัคร Microsoft Azure
      • รู้จักกับ Resource Groups
      • สร้างเว็บตัวแรกกัน
      • สร้าง Virtual Machine กัน
      • ประเภทของคลาว์เซอร์วิส
      • มาสร้าง Logic App กัน
      • มาสร้าง Function App กัน
      • คลาว์คิดเงินยังไง ?
      • Cloud Native
      • Guideline for Cloud scaling
      • Auto Scaling
    • 👶Azure App Services
    • 👶App Service Plan
    • 👶Azure Storage
      • Blob storage
        • ลองสร้างที่เก็บไฟล์กันเลย
        • เข้าใจ Blob storage ให้มากขึ้น
        • ลองเขียนโค้ดอัพโหลดไฟล์กันบ้าง
        • สร้างเว็บจากที่ฝากไฟล์บนคลาว์
    • 👶Azure Bot Service
      • Bot เข้าใจเราได้ยังไงกันนะ
    • 👶Azure Cognitive Services
      • การสร้าง Cognitive Services
      • การ Login ด้วยใบหน้า
      • อ่านลายมือจากรูปเป็นตัวอักษร (OCR)
      • เขียน AI แยกของต่างๆทำยังไง?
      • เขียนแอพ ทายอายุ บอกเพศ ง่ายจิ๊ดเดียว
      • เขียนแอพให้ AI อธิบายรูปเป็นภาษาคน
    • 👶Machine Learning Studio
      • มาสร้าง AI ของแท้ตัวแรกของเรากัน
      • สร้าง AI ตัดสินใจอนุมัติบัตรเครดิต 💳
      • ลองเรียกใช้ AI ของเรากัน
    • 👶Azure Service Fabric
      • สร้าง Service Fabric กัน
    • 👶Blockchain
      • Blockchain ทำงานยังไง ?
      • Consensus Algorithm คืออะไร ?
      • สร้าง Blockchain ใช้เองกัน !
      • หัดเขียน Smart Contract กัน
    • 👶Power BI
    • 👶Azure Web App
      • เซิฟเวอร์บนคลาว์ ราคา? ต่าง?
    • 👶Azure DevOps
      • เล่น Azure DevOps กัน
      • เล่นกับ Repository
      • ลองทำ Continuous Integration (CI)
      • ลองทำ Continuous Delivery (CD)
      • เล่น Kanban Board
    • 🤠Cloud Playground
      • การป้องกันความลับหลุดตอนที่ 1
      • การป้องกันความลับหลุดตอนที่ 2
      • การป้องกันความลับหลุดตอนที่ 3
      • การป้องกันความลับหลุดตอนจบ
  • Software Testing
    • 👦Test-First Design
    • 👦Test-Driven Development
      • 1.มารู้จักกับ TDD กันดีกว่า
      • 2.Test cases เขาเขียนกันยังไงนะ
      • 3.เครื่องมือในการทดสอบ
      • 4.การใช้ Theory และ InlineData
      • 5.โค้ดที่ทดสอบได้
      • 6.Mantra of TDD
      • 7.Functional & None-Functional testing
      • 8.Manual vs Automation testing
      • 9.Automation Frameworks in .NET
      • 10.Mock Framework
      • 11.มาเรียนการใช้ Moq กันเถอะ
      • 12.สรุป
  • Web
    • 👦Web API
      • 1.Web API คืออะไร
      • 2.ติดตั้ง .NET Core SDK
      • 3.สร้าง Web API ตัวแรกกัน
      • 4.Verbs
      • 5.Swagger เพื่อคู่ API
      • 6.การใช้ Model
      • 7.เรียก Web API ผ่าน Postman
      • 8.มาจัดกลุ่ม API กัน (1/2)
      • 9.มาจัดกลุ่ม API กัน (2/2)
  • Software Design
    • 🤴Design Patterns
      • 🦈Creational patterns
        • Abstract Factory
        • Builder
        • Factory Method
        • Prototype
        • Singleton
      • 🦈Structural patterns
        • Adapter
        • Bridge
        • Decorator
        • Facade
        • Proxy
      • 🦈Behavioral patterns
        • Chain of Responsibility
        • Command
        • Iterator
        • Mediator
        • Memento
        • Observer
        • State
        • Strategy
        • Template Method
        • Visitor
Powered by GitBook
On this page
  • 🧐 โจทย์
  • 🧒 แก้โจทย์ครั้งที่ 1
  • 🐱‍🐉 ปัญหาที่ 1
  • 🐱‍🐉 ปัญหาที่ 2
  • 🐱‍🐉 ปัญหาที่ 3
  • 🐱‍🐉 ปัญหาที่ 4
  • 🧒 แก้โจทย์ครั้งที่ 2
  • 🔥 วิเคราะห์ปัญหา
  • 🔥 แก้ไขปัญหา
  • 🤔 แล้วถ้ามันเป็นคลาสลูกล่ะ ?
  • 🤔 Prototype คือไย ?
  • 🔥 จุดกำเหนิด
  • 🔥 ผลจากการใช้
  • 🔥 วิธีการใช้
  • 🤔 ทำไมต้องใช้ด้วย ?
  • 🎯 บทสรุป
  • 👍 ข้อดี
  • 👎 ข้อเสีย
  • 🤙 ทางเลือก

Was this helpful?

Export as PDF
  1. มือใหม่หัดเขียนโค้ด
  2. Design Patterns
  3. Creational Patterns

Prototype Pattern

แนวคิดในการก๊อปปี้ object แบบง่ายๆ

Previous🏗️ Builder PatternNextStructural Patterns

Last updated 5 years ago

Was this helpful?

เจ้าตัวนี้ผมขอตั้งชื่อเป็นภาษาไทยว่า ต้นแบบ ซึ่งมันอยู่ในกลุ่มของ 🤰 โดยเจ้าตัวนี้มันจะมาช่วยให้เราสามารถ ก๊อปปี้ object ตัวหนึ่ง ออกไปเป็นอีกตัวหนึ่งได้แบบง่ายๆ ซึ่งอ่านแล้วก็อาจจะ งงๆ ว่าทำไมต้องทำ ดังนั้นไปดูตัวอย่างปัญหาของเรากันดีกั่ว

แนะนำให้อ่าน บทความนี้เป็นส่วนหนึ่งของมหากาพย์ Design Patterns ที่จะมาเป็น guideline ในการแก้ปัญหาในการออกแบบซอฟต์แวร์โปรเจค หากใครสนใจอยากเข้าใจตั้งแต่ต้นว่ามันคืออะไร และเจ้า patterns ทั้ง 23 ตัวมีอะไรบ้าง ก็สามารถจิ้มตรงนี้เพื่อไปอ่านบทความหลักได้เบยครัช

หมายเหตุ เนื้อหาของบทความนี้จะเน้นให้เข้าใจหลักการทำงานของ Design Patterns แต่ละตัว โดยใช้เกม Ragnarok เป็นการอธิบาย ซึ่งบางอย่างอาจจะไม่ตรงกับตัวเกมจริงๆนะขอรับ Gravity อย่ามาจับผมนะผมโดนแมวน้ำครอบงำ + รู้เท่าไม่ถึงการ + ผมเป็นคนดี + ผมมีลูกมีเมียมีสามีที่ต้องดูแล 😭

เกลียด ชอบ ถูกใจ อยากติดตาม อยากติชมแนะนำด่าทอ หรืออะไรก็แล้วแต่ (ห้ามมายืมเงิน) จิ้มลงมาที่เพจนี้ได้เลย และจะเป็นประคุณอันล้นพ้นถ้ากด Like + Follow + Share ให้ด้วยขอรับ น้ำตาจิไหล 🥺

🧐 โจทย์

สมมุติว่าเรามี object ของตัวละครอยู่ 1 ตัวซึ่งมีข้อมูลคือ มีเลเวล 2, ใส่หมวกกวาง, อาชีพนักผจญภัยฝึกหัด, พลังชีวิต 20 และ พลังเวทมนต์ 12 ตามรูปด้านล่าง

แล้วด้วยเหตุผลอะไรก็ตามแต่ ทำให้เราต้องสร้าง object ที่มีข้อมูลแบบเดียวกันแป๊ะๆเลย เราจะทำยังงุยกันน๊า ?

🧒 แก้โจทย์ครั้งที่ 1

หลายคนพอเห็นโจทย์แล้วก็ยิ้มหวานหมูเลย เพราะเราก็แค่ไปสร้าง object ใหม่ขึ้นมา โดยเอาข้อมูลจาก object เก่าไปยัดใส่ object ใหม่เท่านั้นเองก็เสร็จแล้วนิน่า ซึ่งสมมุติว่าตัวละครมันถูกสร้างมาจากคลาสประมาณนี้ละกันนะ

ดังนั้นโค้ดเราก็จะออกมาราวๆนี้ชิมิ ?

Character object2 = new Character();
object2.Level = object1.Level;
object2.Hat = object1.Hat;
object2.Class = object1.Class;
object2.HP = object1.HP;
object2.SP = object1.SP;

สมมุติว่า object ต้นฉบับของเราอยู่ในตัวแปรที่ชื่อว่า object1 นะ

จากโค้ดด้านบนก็ดูเหมือนว่าเราจะได้ผลลัพท์เป็นแบบด้านล่างละชิมิ?

🐱‍🐉 ปัญหาที่ 1

อะเชคราวนี้เรา ลองให้ object2 เปลี่ยนไปใส่หมวกแซนต้า กับ แก้พลังชีวิตเป็น 55 ดูดิ๊ ตามโค้ดด้านล่าง

object2.Hat.Name = "Santa Hat";
object2.HP = 55;

ซึ่งผลลัพท์ที่เราจะได้ก็คือ

โค้ดของเราแก้ไขข้อมูลให้กับ object2 เท่านั้น ไม่ได้ยุ่งอะไรกับ object1 เลย แต่การแก้ไขครั้งนี้ดันมีผลกับ object1 ด้วยในบางอย่าง เช่น หมวกโดนเปลี่ยนเหมือนกันทั้งคู่ แต่พลังชีวิตกลับเปลี่ยนแค่ object2 เท่านั้น

🐱‍🐉 ปัญหาที่ 2

แล้วถ้าคลาสของเรามันไม่ได้ง่ายแบบนั้นล่ะ เช่นมันมีพวก Private members อยู่ในนั้นด้วยล่ะ เราจะเอาค่ามันมาใส่ใน object 2 ได้ยังไง? ตามรูปด้านล่าง

จากรูปด้านบน เราไม่มีทางเข้าถึงตัวแปร privateData เลย ดังนั้นเราก็จะไม่มีทางกำหนดค่านี้ให้กับ object 2 ได้เลยเช่นกัน

🐱‍🐉 ปัญหาที่ 3

ถ้ากรณีที่เลวร้ายกว่านั้นคือ เราไม่รู้ว่า object ที่เราได้มามันถูกสร้างมาจาก class อะไรล่ะ เช่น เรามี object 1 โดยมันอยู่ในรูปของ interface ตามโค้ดด้านล่าง

public interface ICharacter { ... }

ICharacter object1;
ICharacter object2 = new ???

จากโค้ดด้านบนมันจะทำให้เราไม่สามารถสร้าง object2 ได้เลย เพราะเราไม่รู้ว่าจะไป new class อะไรนั่นเอง

🐱‍🐉 ปัญหาที่ 4

ถ้า Object 1 ของเรามันไปใช้คลาสอื่นๆอีกเต็มไปหมดเลย ตามรูปด้านล่าง แล้วเราจะต้องไปค่อยๆสร้างข้อมูลแต่ละตัวให้กับ Object 2 แล้วล่ะก็ นั่นหมายความว่าเรา ทุกครั้งที่เราจะก๊อปปี้ object 1 มันจะเกิด Dependency วุ่นวายเต็มแถวๆนั้นไปหมดเลย อ่ะดิ

จะสร้าง Object 2 ได้ต้องไป import เจ้าพวกคลาส Equipment, Inventory, Skill, Status มาก่อนไม่งั้นสร้าง object พวกนั้นไม่ได้

นี่มันเกิดอะไรกันขึ้นนะ? ปัญหามันจะเยอะไปหน๋ายยย แล้วเราจะแก้ปัญหาพวกนี้ยังไงดีอ๊าาาาา 😭

🧒 แก้โจทย์ครั้งที่ 2

🔥 วิเคราะห์ปัญหา

(จากปัญหาที่ 1) เรื่องนี้ไม่ได้เกี่ยวข้องโดยตรงกับ Design Pattern ตัวนี้เท่าไหร่ แต่มันเป็นเรื่องพื้นฐานในการเขียนโปรแกรม นั่นคือเรื่องของการใช้ Value type กับ Reference type นั่นเอง ซึ่งมันทำให้เกิดปัญหาหมวกเปลี่ยนทั้ง 2 objects โดยที่เราไม่ตั้งใจ ส่วนวิธีการแก้ไขเจ้าเรื่องนี้เราต้อง เข้าใจว่า Value type ต่างกับ Reference type ยังไงเสียก่อน ถึงจะสามารถแก้ปัญหาตัวนี้และตัวถัดไปได้ขอรับ

(จากปัญหาที่ 2) ตัวข้อมูลที่เราเข้าถึงไม่ได้ เช่น protected, private, internal เราสามารถแก้ให้เข้าถึงด้วยช่องทางอื่นๆก็ได้ แต่ไม่ใช่เรื่องที่ดี เพราะมันจะเสียคุณสมบัติ Encapsulation และความปลอดภัยไป (ดังนั้นไม่ขอพูดถึงวิธีนี้) ซึ่งตัวที่มีสิทธิ์เข้าถึงข้อมูลพวกนั้นได้จริงๆก็คือ ตัวคลาสมันเองนั่นแหละ ถึงจะเหมาะสมสุด

(จากปัญหาที่ 3) เราไม่มีทางรู้เลยว่า class ที่แท้จริงของมันคืออะไร ถ้าเราไม่นั่ง debug หรือไล่ไปดู source code ซึ่งการไล่หา class ที่แท้จริงของมันไม่ใช่เรื่องที่ดีนัก เพราะหลักในการออกแบบจริงๆเรา ไม่ควรทำงานกับ Concrete class ยังไงล่ะ

🔥 แก้ไขปัญหา

จากปัญหาต่างๆที่ว่ามาถ้าวิเคราะห์ดีๆจะพบว่ามันเกิดจาก เราพยายามจะไปสร้าง object เอง ยังไงล่ะ ซึ่งของบางอย่างเราก็ไม่มีสิทธิ์จะเข้าถึงได้ หรือ เราก็ไม่รู้ด้วยซ้ำว่าจริงๆแล้วมันคือตัวอะไร ดังนั้นแทนที่เราจะไปสร้าง object ขึ้นมาเอง เราก็โยนภาระให้กับ object ที่มีสิทธิ์เข้าถึงตัวแปรต่างๆได้ และ มันรู้ว่ามันเกิดจากคลาสอะไรด้วยนั่นเอง ซึ่งในที่นี้ก็คือ ตัวมันเอง นั่นแหละ

ดังนั้นเราก็จะเพิ่มเมธอดในการก๊อปปี้ให้กับคลาส Character เข้าไป 1 ตัวนั่นก็คือ Clone นั่นเองตามรูป

เพราะคลาส Character สามารถเข้าถึง private members ได้ทุกตัวอยู่แล้วเลยไม่มีปัญหาที่จะเข้าถึงตัวแปร privateData ยังไงล่ะ ตามโค้ดด้านล่างเบย

public class Character
{
    public int HP;
    public int SP;
    public int Level;
    public string Class;
    private int privateData;

    public Character Clone()
    {
        return new Character
        {
            HP = HP,
            SP = SP,
            Level = Level,
            Class = Class,
            privateData = privateData
        };
    }
}

เพียงแค่นี้ปัญหาข้อ 2 ก็ถูกแก้ไขไปเรียบร้อยแล้ว (ส่วนข้อ 1 ก็ทำโคลนออกมาเหมือนกัน หรือจะสร้าง object ใหม่ก็แล้วแต่ความยากง่ายของมัน)

หรือต่อให้มันเป็น interface ตามรูปด้านล่าง (ที่เป็นปัญหาในข้อ 3) เจ้าเมธอด Clone ก็ทำงานได้เช่นเคยนะจ๊ะ

จากที่ทำมาทั้งหมด ปัญหาข้อ 4 ก็จะหายไปเอง เพราะเวลาใครอยากจะก๊อปปี้ object ก็เรียกใช้งานเมธอด Clone เท่านั้นเอง ไม่ทำให้เกิด Dependency ไปเลอะที่อื่นแล้วตามโค้ดด้านล่างเบย

ICharacter object1;
ICharacter object2 = object1.Clone();

จากโค้ดด้านบน ไหนลองเอา object2 มาเปลี่ยนเป็นหมวกแซนต้าแบบเดิมดูดิ๊

object2.Hat.Name = "Santa Hat";

ซึ่งผลลัพท์ที่ได้ก็จะทำให้ ตัวละครเป็น object คนละตัวกันอย่างแท้จริง เพียงแต่ข้อมูลมันถูกก๊อปปี้มาจาก object1 เท่านั้นเอง ตามรูปด้านล่าง

🤔 แล้วถ้ามันเป็นคลาสลูกล่ะ ?

จากที่ทำมาทั้งหมดเราจะสามารถก๊อปปี้ object จากคลาส Character ได้แล้ว แต่ถ้าเกิดว่ามีคลาสอื่นมา inheritance จากคลาสนี้ไปตามรูปด้านล่างล่ะ ซึ่งคลาสเหล่านั้นอาจจะมี members หรือ private members ที่ต่างจากคลาสแม่ก็เป็นได้นะ

เพื่อการออกแบบให้ยืดหยุ่นรองรับกรณีคลาสลูกด้วย ดังนั้นเราก็จะทำให้เจ้าเมธอด Clone มันเป็นกลางๆนั่นเอง เพื่อให้คลาสอื่นๆสามารถเอาไปปรับแก้ในรูปแบบของตัวเองต่อได้ง่ายๆ โดยการเปลี่ยนให้มันส่งค่า object กลับไป และให้คลาสลูกสามารถทำ override จากคลาสแม่ต่อได้

ดังนั้นเวลาที่เราอยากจะให้คลาสมันมีความสามารถในการก๊อปปี้ได้ เราสามารถเลือกทำได้หลายวิธีเช่นทำเป็น abstract class ไว้ เพื่อให้ concrete class เป็นคนจัดการต่อ

หรือเราจะสร้าง interface สำหรับทำก๊อปปี้ที่เป็นกลางๆเอาไว้ แล้วให้ concrete class ไปจัดการก็ได้เช่นกัน

🤔 Prototype คือไย ?

🔥 จุดกำเหนิด

ในบางทีการก๊อปปี้ object ก็ไม่ใช่เรื่องง่าย เพราะบางทีเราก็ไม่รู้เหมือนกันว่าเราจะต้องสร้างมันจากคลาสไหน หรือบางทีเราก็ไม่สามารถเข้าไปกำหนดค่า private members ของมันได้ แถมไหนจะเรื่อง dependency ที่จะตามมาอีก

🔥 ผลจากการใช้

เราสามารถก๊อปปี้ object ที่มีค่าด้านในเหมือนกับต้นฉบับได้แบบไม่ผิดเพี้ยน เข้าถึงไส้ในมันได้ทะลุถึงไส้ถึงพุง แถมยังไม่ต้องมากังวลในเรื่องของ concrete class ที่จะสร้าง และ dependency ต่างๆที่จะตามมาด้วย โดยการเรียกผ่าน method เดียวเท่านั้นเอง

🔥 วิธีการใช้

ตรงจุดนี้จะขออธิบายออกเป็นทีละขั้นตอนแบบนี้ละกัน คนที่พึ่งหัดออกแบบจะได้เข้าใจได้ง่ายๆนะ ซึ่งในรอบนี้จะอธิบายในการใช้ interface ดูบ้างนะ เพราะเห็นตัวอย่างการทำแบบ abstraction ไปแล้ว

ถ้าเราอยากจะให้คลาสต่างๆมีความสามารถในการก๊อปปี้ได้ล่ะก็ เราก็จะสร้าง interface กลางๆขึ้นมา 1 ตัว ที่เอาไว้ใช้ในการก๊อปปี้อะไรก็ได้ ตามรูปด้านล่าง

ส่วนคลาสไหนอย่าจะให้มันมีความสามารถในการก๊อปปี้ เราก็แค่ implement interface ตัวนั้นซะ ตามรูปด้านล่าง

ส่วนถ้ามันมีคลาสลูก ก็ให้คลาสลูกทำการ override ไปจัดการในส่วนที่มันต่างกับของคลาสแม่ซะ ตามรูปด้านล่าง

จากที่ร่ายยาวมาทั้งหมดเราก็จะได้แนวทางในการออกแบบที่ชื่อว่า Prototype Pattern ออกมา ซึ่งมีหน้าตาประมาณรูปด้านล่างนี้นั่นเองครัช

ไหนลองเอาที่เราออกแบบมาเทียบกันดูดิ๊ ... เหมือนกันเปี๊ยบเบย ต่างกันแค่ในตัวอย่างนี้ไม่ได้ทำเป็น interface เฉยๆ ซึ่งจะทำก็ได้ไม่ทำก็ได้แบ๊วแต่เรย

🤔 ทำไมต้องใช้ด้วย ?

จากปัญหาต่างๆที่ว่าไว้ในตอนแรก เราจะเห็นถึงความวุ่นวายในการสร้าง object แล้วชิมิ ดังนั้นถ้าเรานำ Prototype Pattern ไปใช้ มันจะ ช่วยลดความซับซ้อนในการสร้างและก๊อปปี้ข้อมูล จาก object A ไป object B ได้ด้วย เพราะความซับซ้อนทั้งหมดมันถูกซ่อนไว้ภายในเมธอด Clone แล้วยังไงล่ะ

🎯 บทสรุป

👍 ข้อดี

การนำ Prototype Pattern มาใช้งานนั้นจะช่วย ลดการผูกกันของโค้ดลง เพราะเราไม่ต้องไปวุ่นวายกับ Concrete class และ Dependency ต่างๆของมันอีกแล้ว แถมยังใช้งานได้ง่ายอีกด้วย

👎 ข้อเสีย

เพิ่มความซับซ้อนโดยไม่จำเป็น ถ้า object มันสามารถ copy ค่าได้ง่ายๆอยู่แล้วจะ new object ใหม่ธรรมดาอาจจะง่ายกว่า และถ้า object มีการอ้างกันแบบงูกินหาง (Circular references) จะทำได้ยาก และอาจเกิดปัญหาตามมาภายหลัง

เกร็ดความรู้ Circular references คือการที่ object A ไปอ้างถึง object B และเจ้า object B ก็ดันมีการอ้างกลับมาที่ object A เช่นกัน ตามโค้ดด้านล่างนี้

var a = new ObjectA();
var b = new ObjectB();
a.Ref = b;
b.Ref = a;

🤙 ทางเลือก

ข้อควรระวัง อย่านำ Prototype Pattern ไปใช้มั่วซั่ว เพราะมันทำให้โค้ดของเราซับซ้อนขึ้นเยอะเลยแทนที่เราจะใช้คำสั่ง new แบบปรกติ ดังนั้นให้ชั่งน้ำหนักให้ดีเสียก่อนว่าปัญหาที่เราเจออยู่นั้น มันวุ่นวาย เทสยาก โค้ดมันผูกกันอยู่เยอะหรือเปล่า ถ้าชั่งน้ำหนักแล้ว + มีเหตุผลที่เพียงพอที่จะใช้ก็จงใช้ให้สบายใจไปเถิด

แนะนำให้อ่าน สำหรับใครที่อยากศึกษาต่อว่า Value type กับ Reference type คืออะไร สามารถไปทำความเข้าใจได้กับบทความตัวนี้ขอรับ มันเป็นเรื่องพื้นฐานสุดๆของการเขียนโปรแกรม ดังนั้นขอไม่ลงรายละเอียดตัวนี้ต่อนะ

แนะนำให้อ่าน อะไรนะลืมการทำ encapsulation ไปแล้วรึ งั้นไปทบทวนได้จากลิงค์นี้เบย

แนะนำให้อ่าน หลักในการออกแบบขั้นพื้นฐานคือการ ทำงานกับ Abstraction นั่นเอง ซึ่งถ้าอยากศึกษาว่าทำไมต้องเป็นแบบนั้นก็ไปอ่านได้จากลิงค์นี้ ส่วนถ้าอยากเข้าใจลึกๆถึงแก่นจริงๆลองศึกษาได้จากบทความนี้

โดยปรกติเรื่องการก๊อปปี้ object นั้นเป็นปัญหามานานแล้ว ดังนั้นในแต่ละภาษาเขาจะมีวิธีการจัดการของเขาเองอยู่แล้ว เช่นของภาษา C# ก็จะมี interface ที่ชื่อว่า อยู่แล้วเราไม่ต้องไปสร้างเอง หรือพวกเมธอด ดังนั้นจงไปศึกษามาตรฐานของภาษาที่ตัวเองใช้ให้ดีก่อนนะขอรับ

เกลียด ชอบ ถูกใจ อยากติดตาม อยากติชมแนะนำด่าทอ หรืออะไรก็แล้วแต่ (ห้ามมายืมเงิน) จิ้มลงมาที่เพจนี้ได้เลย และจะเป็นประคุณอันล้นพ้นถ้ากด Like + Follow + Share ให้ด้วยขอรับ น้ำตาจิไหล 🥺

👦
🤰
🎎
Value type vs Reference type
💖 Encapsulation
Creational Pattern
Dependency-Inversion Principle
ICloneable
MemberwiseClone
Mr.Saladpuk
Creational Patterns
👦 Design Patterns
Mr.Saladpuk
อยากได้ object ใหม่ที่มีข้อมูลเหมือนตัวเดิมเลยอ่าาาา
หมวกของ object 1 ถูกเปลี่ยนด้วยเฉยเลย
อุ๊ต๊ะมี private member ด้วย !
ใช้คลาสอื่นๆเต็มไปหมดเบย
ทำเป็น abstract class ซะ
ทำเป็น interface กลางๆ ใช้ได้ทุกสถานะการณ์