“สวัสดี อามีโก้!”

"สวัสดี บิลาโบ!"

"หัวข้อของเราในวันนี้จะไม่เพียงแค่น่าสนใจเท่านั้น แต่มันจะเป็นมหากาพย์อย่างจริงจัง"

"วันนี้ผมจะพาคุณไปดูว่ารูปแบบการออกแบบคือ อะไร "

"เจ๋ง! ฉันได้ยินเกี่ยวกับพวกเขามามาก ฉันรอไม่ไหวแล้ว!"

"โปรแกรมเมอร์ที่มีประสบการณ์ต้องเขียนคลาสจำนวนมาก แต่ส่วนที่ยากที่สุดของงานนี้คือการตัดสินใจว่าจะสร้างคลาสใดและจะแบ่งงานระหว่างกันอย่างไร"

"ยิ่งพวกเขาแก้ปัญหาดังกล่าวมากเท่าไหร่ พวกเขาก็ยิ่งตระหนักว่าวิธีแก้ปัญหาบางอย่างดี ในขณะที่บางอย่างไม่ดี"

"วิธีแก้ปัญหาที่ไม่ดีมักจะสร้างปัญหามากกว่าที่พวกเขาแก้ไข พวกเขาขยายได้ไม่ดี สร้างข้อจำกัดที่ไม่จำเป็นมากมาย ฯลฯ และวิธีแก้ปัญหาที่ดีนั้นตรงกันข้าม"

"มีการเปรียบเทียบบางอย่างที่คุณสามารถทำได้หรือไม่"

"สมมติว่าคุณกำลังสร้างบ้าน และคุณกำลังคิดว่าจะสร้างจากอะไร คุณตัดสินใจว่าคุณต้องการผนัง พื้น และเพดาน ผลก็คือ คุณสร้างบ้านที่มีหลังคาเรียบและไม่มีหลังคา ฐานรากบ้านจะร้าว หลังคารั่ว เป็นวิธีแก้ไขที่ไม่ดี"

"ในทางกลับกัน บ้านที่ประกอบด้วยฐานราก ผนัง และหลังคาทรงจั่วน่าจะเป็นทางออกที่ดี หิมะตกหนักไม่ใช่ปัญหา เพราะหิมะจะเลื่อนลงมาจากหลังคา และดินที่เคลื่อนตัวก็ไม่มีอะไรต้องกลัว เพราะฐานรากจะช่วยให้มั่นใจได้ ความมั่นคง เราจะเรียกว่าทางออกที่ดี”

"เข้าใจแล้ว ขอบคุณ"

"ตกลง ฉันจะดำเนินการต่อ"

"ในเวลาต่อมา วิธีแก้ปัญหาที่ดีถูกเรียกว่ารูปแบบการออกแบบ ในขณะที่สิ่งที่ไม่ดีเรียกว่ารูปแบบต่อต้าน"

"รูปแบบการออกแบบเปรียบเสมือนคำตอบของคำถาม ยากที่จะเข้าใจหากคุณไม่เคยได้ยินคำถาม"

" รูปแบบประเภทแรกคือรูปแบบที่สร้างสรรค์ รูปแบบดังกล่าวอธิบายวิธีแก้ปัญหาที่ดีที่เกี่ยวข้องกับการสร้างวัตถุ"

"อะไรที่ซับซ้อนมากในการสร้างวัตถุ?"

"เมื่อมันเกิดขึ้น นั่นคือสิ่งที่เรากำลังจะสำรวจในตอนนี้"

รูปแบบซิงเกิล

รูปแบบการออกแบบ: singleton, โรงงาน, วิธีการโรงงาน, โรงงานนามธรรม - 1

"บ่อยครั้งในโปรแกรม สามารถมีอ็อบเจกต์ได้เพียงชุดเดียว ตัวอย่างเช่น คอนโซล ตัวบันทึก ตัวเก็บขยะ ฯลฯ"

" วิธีแก้ปัญหาที่ไม่ดี:อย่าสร้างออบเจกต์ใดๆ — เพียงแค่สร้างคลาสที่มีเมธอดเป็นสแตติกทั้งหมด"

" ทางออกที่ดี:  สร้างวัตถุเดียวและเก็บไว้ในตัวแปรคงที่ ป้องกันการสร้างวัตถุที่สองของคลาส ตัวอย่างเช่น:"

ตัวอย่าง
class Sun
{
 private static Sun instance;
 public static Sun getInstance()
 {
  if (instance == null)
  instance = new Sun();

  return instance;
 }

 private Sun()
 {
 }
}
เรียกว่าอย่างไร
Sun sun = Sun.getInstance();

"มันง่าย"

"อย่างแรก เราทำให้คอนสตรัคเตอร์เป็นแบบส่วนตัว ตอนนี้สามารถเรียกมันได้จากในคลาสของเราเท่านั้น เราได้บล็อกการสร้างออบเจกต์ Sun ทุกที่ ยกเว้นภายในเมธอดของคลาส Sun"

"ประการที่สอง วัตถุของคลาสนี้สามารถรับได้โดยการเรียกเมธอด getInstance() เท่านั้น ไม่เพียงแต่เป็นเมธอดเดียวที่สามารถสร้างวัตถุดวงอาทิตย์ได้ แต่ยังทำให้มั่นใจได้ว่ามีวัตถุดังกล่าวเพียงชิ้นเดียว"

"ฉันเห็น."

"เมื่อคุณคิดว่า «ตอนนี้ ฉันจะทำอย่างนั้นได้อย่างไร» รูปแบบจะบอกว่า «คุณสามารถลองทำสิ่งนี้ได้ — นี่เป็นหนึ่งในวิธีแก้ปัญหาที่ดีที่สุด»"

“ขอบคุณ ตอนนี้ทุกอย่างเริ่มชัดเจนแล้ว”

"คุณสามารถอ่านเกี่ยวกับรูปแบบนี้ได้  ที่นี่ "

รูปแบบโรงงาน.

รูปแบบการออกแบบ: singleton, โรงงาน, วิธีการโรงงาน, โรงงานนามธรรม - 2

"นี่เป็นสถานการณ์ที่โปรแกรมเมอร์เผชิญบ่อยมาก คุณมีคลาสพื้นฐานและคลาสย่อยมากมาย ตัวอย่างเช่น คลาสตัวละครในเกม (GamePerson) และคลาสสำหรับตัวละครอื่นๆ ทั้งหมดที่สืบทอดมา"

"สมมติว่าคุณมีชั้นเรียนต่อไปนี้:"

ตัวอย่าง
abstract class GamePerson
{
}

class Warrior extends GamePerson
{
}

class Mag extends GamePerson
{
}

class Troll extends GamePerson
{
}

class Elf extends GamePerson
{
}

"คำถามคือเราจะจัดการการสร้างวัตถุของคลาสเหล่านี้อย่างยืดหยุ่นและสะดวกได้อย่างไร"

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

" รูปแบบ โรงงานเป็นทางออกที่ดี"

"ขั้นแรก เราต้องสร้าง enum ที่มีค่าสอดคล้องกับคลาสต่างๆ"

"ประการที่สอง สร้าง คลาส Factory พิเศษ ที่มีเมธอดแบบสแตติกที่สร้างออบเจกต์ตามค่า enum"

"ตัวอย่างเช่น:"

ตัวอย่าง
public enum PersonType
{
 UNKNOWN,
 WARRIOR,
 MAG,
 TROLL,
 ELF,
}

public class PersonFactory
{
 public static GamePerson createPerson(PersonType personType)
 {
  switch(personType)
  {
   WARRIOR:
   return new Warrior();
   MAG:
   return new Mag();
   TROLL:
   return new Troll();
   ELF:
   return new Elf();
   default:
   throw new GameException();
  }
 }
}
เรียกว่าอย่างไร
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

"กล่าวอีกนัยหนึ่งคือ เราสร้างคลาสพิเศษเพื่อจัดการการสร้างวัตถุ"

"ใช่."

"แล้วสิ่งนี้ให้ข้อดีอะไรบ้าง"

"ขั้นแรก ในคลาสนี้ วัตถุสามารถเริ่มต้นได้ด้วยข้อมูลที่จำเป็น"

"ประการที่สอง คุณสามารถส่งค่า enum ที่ต้องการระหว่างเมธอดได้มากเท่าที่คุณต้องการเพื่อสร้างวัตถุที่ต้องการในท้ายที่สุด"

"ประการที่สาม จำนวนฟิลด์ enum ไม่จำเป็นต้องตรงกับจำนวนคลาส อาจมีอักขระหลายประเภท แต่มีไม่กี่คลาส"

"ตัวอย่างเช่นMag & Warriorอาจใช้คลาสเดียว (มนุษย์) แต่มีความแข็งแกร่งและคุณสมบัติเวทย์มนตร์ต่างกัน (อาร์กิวเมนต์ตัวสร้าง)"

"นี่คือลักษณะที่ปรากฏ (เพื่อความชัดเจน ฉันได้เพิ่มดาร์คเอลฟ์เข้าไปด้วย):"

ตัวอย่าง
public enum PersonType
{
 UNKNOWN,
 WARRIOR,
 MAG,
 TROLL,
 ELF,
 DARK_ELF
}

public class PersonFactory
{
 public static GamePerson createPerson(PersonType personType)
 {
  switch(personType)
  {
   WARRIOR:
   return new Human(10, 0); // Strength, magic
   MAG:
   return new Human(0, 10); // Strength, magic
   TROLL:
   OGR:
   return new Troll();
   ELF:
   return new Elf(true); // true – good, false – evil
   DARK_ELF:
   return new Elf(false); // true – good, false – evil
   default:
   throw new GameException();
  }
 }
}
เรียกว่าอย่างไร
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

"ในตัวอย่างด้านบน เราใช้คลาสเพียงสามคลาสเพื่อสร้างออบเจกต์หกประเภท ซึ่งสะดวกมาก ยิ่งกว่านั้น เรามีตรรกะทั้งหมดนี้รวมอยู่ในคลาสเดียวและเมธอดเดียว"

“ตอนนี้ สมมติว่าเราตัดสินใจสร้างคลาสแยกต่างหากสำหรับ Ogre — เราเพียงแค่เปลี่ยนโค้ดสองสามบรรทัดที่นี่ และไม่ใช่ครึ่งหนึ่งของแอปพลิเคชัน”

“ฉันเห็นด้วย นั่นเป็นทางออกที่ดี”

"และนั่นคือสิ่งที่ฉันกำลังพูดถึง: รูปแบบการออกแบบคือคอลเลกชันของโซลูชันที่ดี"

“ฉันก็อยากรู้ว่าจะใช้มันได้ที่ไหน…”

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

"โอ้ขอบคุณ."

" รูปแบบ โรงงานนามธรรม "

"บางครั้งเมื่อคุณมีวัตถุจำนวนมาก แนวคิดในการสร้างโรงงานสำหรับโรงงานจะแนะนำตัวมันเอง โรงงานแบบนี้เรียกว่าโรงงานนามธรรม "

“จะจำเป็นไปไหน!?”

"สมมติว่าคุณมีวัตถุที่เหมือนกันหลายกลุ่ม แสดงตัวอย่างได้ง่ายกว่า"

"ตอนนี้ สมมติว่าคุณมีสามเผ่าพันธุ์ในเกมของคุณ: มนุษย์ เอลฟ์ และปีศาจ และเพื่อความสมดุล แต่ละเผ่าพันธุ์จะมีนักรบ นักธนู และผู้วิเศษ ผู้เล่นสามารถสร้างวัตถุที่เป็นของเผ่าพันธุ์ที่เขาหรือเธอกำลังเล่นอยู่เท่านั้น ในเกม นี่คือหน้าตาของโค้ด:"

การประกาศชั้นทหาร
class Warrior
{
}
class Archer
{
}
class Mag
{
}
มนุษย์
class HumanWarrior extends Warrior
{
}

class HumanArcher extends Archer
{
}

class HumanMag extends Mag
{
}
เอลฟ์
class ElfWarrior extends Warrior
{
}

class ElfArcher extends Archer
{
}

class ElfMag extends Mag
{
}
ปีศาจ
class DaemonWarrior extends Warrior
{
}

class DaemonArcher extends Archer
{
}

class DaemonMag extends Mag
{
}

และตอนนี้เรามาสร้างเผ่าพันธุ์กัน หรือเรียกอีกอย่างว่ากองทัพก็ได้

กองทัพ
abstract class Army
{
 public Warrior createWarrior();
 public Archer createArcher();
 public Mag createMag();
}
กองทัพมนุษย์
class HumanArmy extends Army
{
 public Warrior createWarrior()
 {
  return new HumanWarrior();
 }
 public Archer createArcher()
 {
  return new HumanArcher();
 }
 public Mag createMag()
 {
  return new HumanMag();
 }
}
กองทัพเอลฟ์
class ElfArmy extends Army
{
 public Warrior createWarrior()
 {
  return new ElfWarrior();
 }
 public Archer createArcher()
 {
  return new ElfArcher();
 }
 public Mag createMag()
 {
  return new ElfMag();
 }
}
กองทัพปีศาจ
class DaemonArmy extends Army
{
 public Warrior createWarrior()
 {
  return new DaemonWarrior();
 }
 public Archer createArcher()
 {
  return new DaemonArcher();
 }
 public Mag createMag()
 {
  return new DaemonMag();
 }
}

“ว่าแต่เจ้าใช้สิ่งนี้ได้อย่างไร”

"คุณสามารถใช้คลาส Army, Warrior, Archer และ Mage ได้ทุกที่ในโปรแกรม และสร้างวัตถุที่จำเป็น — เพียงแค่ส่งวัตถุของคลาสย่อย Army ที่ต้องการ"

"ตัวอย่างเช่น:"

ตัวอย่าง
Army humans = new HumanArmy();
Army daemons = new DaemonArmy();

Army winner = FightSimulator.simulate(humans, daemons);

"ในตัวอย่างด้านบน เรามีคลาสที่จำลองการต่อสู้ระหว่างเผ่าพันธุ์ต่างๆ (กองทัพ) คุณเพียงแค่ต้องผ่านสิ่งของกองทัพ 2 ชิ้น คลาสนั้นใช้พวกมันเพื่อสร้างกองกำลังต่างๆ และทำการต่อสู้เสมือนจริงระหว่างพวกมันเพื่อระบุตัวผู้ชนะ "

"เข้าใจแล้ว ขอบคุณ เป็นแนวทางที่น่าสนใจจริงๆ"

"ทางออกที่ดีไม่ว่าคุณจะพูดอะไร"

"ใช่."

"นี่คืออีกลิงค์ที่ดีในหัวข้อ:  รูปแบบโรงงานนามธรรม "