คำถามติดแท็ก design-patterns

รูปแบบการออกแบบเป็นโซลูชันที่ใช้ซ้ำได้ทั่วไปสำหรับปัญหาที่เกิดขึ้นทั่วไปในการออกแบบซอฟต์แวร์

2
ใช้แพ็คเกจ (อัญมณีไข่ ฯลฯ ) เพื่อสร้างสถาปัตยกรรมที่แยกออก
ประเด็นหลัก เห็นการสนับสนุนที่ดีมากที่สุดแพลตฟอร์มการเขียนโปรแกรมที่ทันสมัยมีการบริหารจัดการแพคเกจ (คิดว่าgem, npm, pipฯลฯ ) ไม่ได้ทำให้ความรู้สึกในการออกแบบโปรแกรมหรือระบบจะประกอบด้วยแพคเกจการพัฒนาภายในเพื่อส่งเสริมและสร้างสถาปัตยกรรมคู่หลวม? ตัวอย่าง ตัวอย่างนี้จะสร้างแพคเกจสำหรับการเข้าถึงฐานข้อมูลรวมถึงการตรวจสอบและส่วนประกอบอื่น ๆ ของระบบ แน่นอนว่าใช้แพ็คเกจภายนอกด้วย จากนั้นระบบของคุณจะนำเข้าและใช้แพ็คเกจเหล่านี้แทนที่จะรวมรหัสไว้ในฐานรหัสของตนเอง การพิจารณา สำหรับฉันดูเหมือนว่าสิ่งนี้จะส่งเสริมการแยกรหัสและช่วยให้สามารถบำรุงรักษาได้เกือบจะเป็นแอพพลิเคชั่นบนเว็บเทียบกับเดสก์ท็อป (มีการใช้งานการอัปเดตเกือบอัตโนมัติโดยใช้ฐานรหัสเดียวสำหรับการใช้งานเดียว ดูเหมือนว่าแนวคิดการออกแบบที่สมเหตุสมผลและมีเหตุผลหรือไม่ สิ่งนี้ใช้จริง ๆ แล้วเป็นวิธีมาตรฐานในการสร้างแอพพลิเคชั่นในปัจจุบันหรือไม่?

4
ฉันควรใช้ความพยายามมากแค่ไหนในการสร้างการออกแบบที่ควบคู่กันอย่างหลวม ๆ
ปัจจุบันฉันเรียนรู้เกี่ยวกับรูปแบบการออกแบบ ฉันคิดว่าคนส่วนใหญ่ยอมรับว่ารูปแบบเหล่านี้เป็นเครื่องมือที่ยอดเยี่ยม แต่ควรใช้กับการกลั่นกรองและไม่ใช่คำตอบสำหรับทุกสิ่ง การใช้งานมากเกินไปจะทำให้แอปพลิเคชันมีความซับซ้อนมากเกินไปโดยมีประโยชน์เพียงเล็กน้อย ควรใช้รูปแบบเฉพาะที่สามารถเป็นทางออกที่ดีที่สุดหรือช่วยในการสร้างทางออกที่ดี (คุณเห็นด้วย?) ด้วยสิ่งนี้ในใจ: หนังสือที่ฉันกำลังอ่าน (รูปแบบการออกแบบหัวแรก) มักเน้นถึงความสำคัญของข้อต่อหลวมๆ การมีเพศสัมพันธ์แบบหลวมนี้ทำได้โดยทำตามหลักการเช่น 'โปรแกรมไปยังส่วนต่อประสานไม่ใช่การใช้งาน' และ 'สรุปสิ่งที่แตกต่าง' โดยพื้นฐานแล้วรูปแบบส่วนใหญ่ที่ฉันได้เรียนรู้มานั้นมีอยู่เป็นส่วนใหญ่เพื่อให้การออกแบบเป็นแบบคู่อย่างอิสระและทำให้มีความยืดหยุ่นมากขึ้น ฉันเข้าใจถึงความสำคัญและประโยชน์ของข้อต่อหลวม แต่คำถามของฉันคือต้องใช้ความพยายามมากแค่ไหนในการสร้างการออกแบบที่มีความยืดหยุ่นและหลวม ผู้ที่คัดค้านรูปแบบการออกแบบบอกว่าค่าใช้จ่ายในการใช้รูปแบบเหล่านี้มักจะมากกว่าประโยชน์ คุณลงทุนเวลามากในการสร้างการออกแบบคู่ที่หลวม ๆ โดยใช้รูปแบบที่จริงแล้ว - ข้อต่อหลวม, 'การตั้งโปรแกรมไปยังส่วนต่อประสาน, ไม่ใช่การใช้งาน' และหลักการเหล่านี้ทั้งหมด - อาจไม่สำคัญนัก สิ่งที่ฉันอยากรู้คือฉันควรใช้ความพยายามในการสร้างระดับนามธรรมและการออกแบบเพิ่มเติมเพียงใดเพื่อให้แอปพลิเคชันของฉันปฏิบัติตามหลักการ OO เช่นข้อต่อหลวมการเขียนโปรแกรมเข้าสู่อินเตอร์เฟส ฯลฯ คุ้มหรือไม่ มัน? ฉันควรใช้ความพยายามมากแค่ไหนในเรื่องนี้?

4
รูปแบบการออกแบบใดที่เหมาะสมกว่าสำหรับการบันทึก
ฉันควรบันทึกเหตุการณ์บางอย่างในโปรแกรม แต่เท่าที่ฉันรู้จะเป็นการดีกว่าถ้าจะเก็บรหัสการบันทึกภายนอกโปรแกรมเพราะมันไม่เกี่ยวกับการใช้งานจริงของโปรแกรม ดังนั้นคุณช่วยบอกฉันได้ไหมว่าฉันควรเก็บรหัสนี้เอาไว้อย่างสมบูรณ์และใช้ผู้สังเกตการณ์และผู้ฟังเพื่อบันทึกเหตุการณ์เท่านั้นหรือไม่ หรือฉันสามารถเพิ่มบรรทัดของรหัสเช่นต่อไปนี้ทุกที่ที่ฉันต้องการบันทึกบางสิ่งบางอย่าง: MyGloriousLogger.getXXXLogger().Log(LogPlace, new LogObject(z1, z2, z3, z4, ..., z99)); ฉันทำผิดพลาดในการใช้รูปแบบการออกแบบของ Observer หรือไม่ ฉันต้องการรูปแบบการออกแบบอื่นหรือไม่ หรือฉันควรหยุดคิดเกี่ยวกับรูปแบบการออกแบบ? PS1 หากฉันต้องการเข้าสู่ระบบโดยใช้ผู้ฟังและผู้สังเกตการณ์เท่านั้นฉันจะต้องเพิ่มและปรับปรุงผู้สังเกตการณ์และผู้ฟังของโปรแกรมอย่างแน่นอน PS2 แน่นอนฉันรู้ว่ามีห้องสมุดที่แตกต่างกันสำหรับการเข้าสู่ระบบใน Java และฉันใช้ java.utils.logging แต่ฉันต้องมี wrapper เพื่อเข้าสู่ระบบวัตถุพิเศษของฉัน

2
จะตรวจสอบกฎโมเดลโดเมนที่ขึ้นกับเนื้อหาของฐานข้อมูลได้ที่ไหน
ฉันกำลังทำงานกับระบบที่อนุญาตให้ผู้ดูแลระบบกำหนดฟอร์มที่มีฟิลด์ แบบฟอร์มที่กำหนดจะถูกใช้เพื่อป้อนข้อมูลไปยังระบบ บางครั้งแบบฟอร์มจะถูกกรอกโดยมนุษย์ผ่าน GUI บางครั้งแบบฟอร์มจะถูกกรอกตามค่าที่รายงานโดยระบบอื่น สำหรับแต่ละฟิลด์ผู้ดูแลระบบสามารถกำหนดกฎการตรวจสอบที่ จำกัด ค่าที่อนุญาตสำหรับฟิลด์ กฎการตรวจสอบสามารถเป็นอะไรก็ได้จาก "ค่าที่ป้อนในฟิลด์ต้องเป็นจริงหรือเท็จ" ถึง "ค่าที่ป้อนในฟิลด์ต้องมีอยู่ในคอลัมน์ A ของตาราง B ในฐานข้อมูล" ผู้ดูแลระบบสามารถเปลี่ยนแปลงกฎการตรวจสอบสำหรับฟิลด์ได้ตลอดเวลา ในสถานการณ์นี้ความคิดเห็นของคุณเป็นสถานที่ที่เหมาะสมที่สุดสำหรับการตรวจสอบว่าแต่ละเขตข้อมูลถูกกรอกอย่างถูกต้องหรือไม่ ฉันมีสองวิธีหลักในใจ: ตัวเลือก # 1: ตรวจสอบความถูกต้องในรูปแบบโดเมน แต่ละวัตถุฟิลด์จะมีกฎการตรวจสอบที่ระบุโดยผู้ดูแลระบบ วัตถุฟิลด์จะมีการอ้างอิงถึง IValidator เมื่อมีความพยายามในการตั้งค่าของฟิลด์ฟิลด์จะผ่านค่าที่กำหนดและกฎการตรวจสอบไปยัง IValidator หากค่าที่ระบุไม่ถูกต้องจะมีการโยน ValidationException และจัดการอย่างเหมาะสมใน GUI / อินเตอร์เฟสไปยังระบบอื่น ข้อดี: การป้องกันที่แข็งแกร่งสำหรับฟิลด์ที่ถูกกำหนดค่าโดยไม่ตั้งใจซึ่งละเมิดกฎการตรวจสอบ จุดด้อย: Data Access Layer ต้องสามารถผ่านการตรวจสอบและสร้างเขตข้อมูลที่ละเมิดกฎการตรวจสอบปัจจุบัน แม้ผู้ดูแลระบบจะเปลี่ยนกฎการตรวจสอบสำหรับเขตข้อมูล แต่เรายังจำเป็นต้องสร้างวัตถุเขตข้อมูลตามข้อมูลเก่าเช่นเมื่อแสดงแบบฟอร์มที่กรอกข้อมูลเมื่อหลายปีก่อน สิ่งนี้อาจแก้ไขได้โดยการเก็บกฎการตรวจสอบปัจจุบันเมื่อใดก็ตามที่เราเก็บฟิลด์ ในการออกแบบนี้โมเดลฟิลด์มีลิงก์ทางอ้อมไปยัง Data Access Layer / Repository …

2
คลาสบริบทในรูปแบบกลยุทธ์
ฉันพยายามที่จะเข้าใจรูปแบบกลยุทธ์และถามตัวเองว่า: คลาสบริบทต้องมีหรือฉันสามารถละทิ้งมันโดยไม่ลดทอนจุดประสงค์ของรูปแบบ? ฉันตกอยู่ในความประทับใจฉันต้องการสวิตช์บางอย่างสำหรับอ่านไฟล์ประเภทต่าง ๆ แต่ไม่ต้องการแฮ็กข้อมูลและจัดการกับการรีแฟคเตอร์ใหม่ในภายหลัง (แม้ว่าแน่นอนว่ามันเกิดขึ้นเสมอว่าโค้ดสามารถรีเฟรชได้ แต่ความคิดคือ: ลอง จะฉลาดเท่าที่จะเป็นไปได้ในการออกแบบล่วงหน้า ... ): ภาพที่นำมาจากวิกิมีเดีย ลูกค้าสามารถมอบหมายโดยตรงไปยังส่วนต่อประสานกลยุทธ์หรือมีบางสิ่งที่ฉันเพิ่งพลาดที่จะเข้าใจเกี่ยวกับคลาสบริบทหรือไม่ interface Reader { // read information from file and fill data list field of Client readFile(); } class ExcelReader implements Reader{ /* */ } class PdfReader implements Reader{ /* */} class Client{ // strategic choice Reader r; …

5
ใน MVC สามารถเรียกค้นข้อมูลพื้นฐานจาก Model ได้หรือไม่ในมุมมอง?
ด้วยแนวคิดของ'ตัวควบคุมผอมแบบจำลองไขมัน'และการยอมรับทั่วไปที่ Views สามารถเรียกใช้โมเดลโดยตรงเมื่อต้องการข้อมูลเพื่อการส่งออกเราควรพิจารณาการจัดการส่วน 'รับและแสดง' ของคำขอภายใน Views ไม่ใช่ตัวควบคุม ตัวอย่างเช่น (พยายามเก็บรหัสที่ค่อนข้างทั่วไป): ตัวควบคุม <?php class Invoice extends Base_Controller { /** * Get all the invoices for this month */ public function current_month() { // as there's no user input let's keep the controller very skinny, // DON'T get data from the Model here, …

7
การใช้เงื่อนไขด้านความปลอดภัยในมุมมองเป็นการละเมิด MVC หรือไม่
บ่อยครั้งที่สิ่งที่ปรากฏต่อผู้ใช้ (เช่นบนหน้าเว็บ) จะขึ้นอยู่กับการตรวจสอบความปลอดภัยเป็นส่วนหนึ่ง ฉันมักจะพิจารณาความปลอดภัยระดับผู้ใช้ / ACL เป็นส่วนหนึ่งของตรรกะทางธุรกิจของระบบ หากมุมมองตรวจสอบความปลอดภัยอย่างชัดเจนเพื่อแสดงองค์ประกอบ UI แบบมีเงื่อนไขจะเป็นการละเมิด MVC โดยมีตรรกะทางธุรกิจหรือไม่

1
รูปแบบการออกแบบที่มีประโยชน์สำหรับการทำงานกับ FragmentManager บน Android
เมื่อทำงานกับแฟรกเมนต์ฉันใช้คลาสที่ประกอบด้วยเมธอดสแตติกที่กำหนดแอ็คชันกับแฟรกเมนต์ สำหรับโครงการใดก็ตามฉันอาจมีคลาสที่เรียกว่าFragmentActionsซึ่งมีวิธีการคล้ายกับต่อไปนี้: public static void showDeviceFragment(FragmentManager man){ String tag = AllDevicesFragment.getFragmentTag(); AllDevicesFragment fragment = (AllDevicesFragment)man.findFragmentByTag(tag); if(fragment == null){ fragment = new AllDevicesFragment(); } FragmentTransaction t = man.beginTransaction(); t.add(R.id.main_frame, fragment, tag); t.commit(); } โดยปกติฉันจะมีวิธีหนึ่งต่อหน้าจอแอปพลิเคชัน ฉันทำสิ่งนี้เมื่อฉันทำงานกับฐานข้อมูลท้องถิ่นขนาดเล็ก (โดยปกติจะเป็น SQLite) ดังนั้นฉันจึงนำไปใช้กับแฟรกเมนต์ซึ่งดูเหมือนจะมีเวิร์กโฟลว์ที่คล้ายกัน ฉันไม่ได้แต่งงานกับมัน คุณจัดระเบียบแอปพลิเคชันของคุณให้เชื่อมต่อกับ Fragments API ได้อย่างไรและคุณคิดว่ารูปแบบการออกแบบ (ถ้ามี) มีอะไรบ้าง

5
วิธีทดสอบหน่วยฟังก์ชันที่ปรับโครงสร้างรูปแบบกลยุทธ์ใหม่แล้วหรือไม่
ถ้าฉันมีฟังก์ชั่นในรหัสของฉันที่จะไป: class Employee{ public string calculateTax(string name, int salary) { switch (name) { case "Chris": doSomething($salary); case "David": doSomethingDifferent($salary); case "Scott": doOtherThing($salary); } } โดยปกติฉันจะ refactor นี้เพื่อใช้ Ploymorphism โดยใช้คลาสโรงงานและรูปแบบกลยุทธ์: public string calculateTax(string name) { InameHandler nameHandler = NameHandlerFactory::getHandler(name); nameHandler->calculateTax($salary); } ตอนนี้ถ้าฉันใช้ TDD ฉันก็จะมีการทดสอบบางอย่างที่ทำงานกับต้นฉบับcalculateTax()ก่อนที่จะทำการรีแฟคเตอร์ อดีต: calculateTax_givenChrisSalaryBelowThreshold_Expect111(){} calculateTax_givenChrisSalaryAboveThreshold_Expect111(){} calculateTax_givenDavidSalaryBelowThreshold_Expect222(){} calculateTax_givenDavidSalaryAboveThreshold_Expect222(){} calculateTax_givenScottSalaryBelowThreshold_Expect333(){} calculateTax_givenScottSalaryAboveThreshold_Expect333(){} …

4
รูปแบบการออกแบบสำหรับการจัดการการตอบสนอง
ส่วนใหญ่เวลาที่ฉันเขียนโค้ดบางอย่างที่จัดการการตอบสนองสำหรับการเรียกใช้ฟังก์ชันบางฉันได้รับโครงสร้างรหัสต่อไปนี้: ตัวอย่าง: นี่คือฟังก์ชันที่จะจัดการการรับรองความถูกต้องสำหรับระบบเข้าสู่ระบบ class Authentication{ function login(){ //This function is called from my Controller $result=$this->authenticate($username,$password); if($result=='wrong password'){ //increase the login trials counter //send mail to admin //store visitor ip }else if($result=='wrong username'){ //increase the login trials counter //do other stuff }else if($result=='login trials exceeded') //do some stuff }else if($result=='banned ip'){ …

6
ทำไมการทำคลาสย่อยแย่เกินไป (และด้วยเหตุนี้เราควรใช้ต้นแบบเพื่อทำไป)
ฉันอ่านเกี่ยวกับรูปแบบการออกแบบและฉันอ่านว่ารูปแบบการออกแบบต้นแบบนั้นมีซับคลาสที่มากเกินไป ทำไมการแบ่งคลาสย่อยไม่ดี การใช้ต้นแบบจะได้ประโยชน์อะไรจากการทำ subclassing

4
การเขียนโปรแกรมความรู้วิธีการออกแบบที่ดี / ไม่ดี
ฉันได้พบเมื่อเร็ว ๆ นี้แนวคิดของการเขียนโปรแกรมความรู้ และฉันก็พบว่ามันค่อนข้างน่าสนใจ แต่ฉันไม่ได้พบกับการอ้างว่ามันเป็นวิธีที่ไม่ดีในการจัดโครงสร้างโปรแกรม ดูเหมือนจะไม่ครอบคลุมหลายสถานที่ ไม่แม้แต่ที่นี่ฉันสามารถพบคำถามใด ๆ เกี่ยวกับเรื่องนี้ คำถามของฉันไม่ได้เกี่ยวกับข้อบกพร่องหรือวิธีการจัดการเอกสาร ฉันพิจารณาเอกสารข้างเคียงของสิ่งที่มันจะมีความหมายสำหรับการไหลของการเขียนโปรแกรมความรู้ ฉันรู้ว่าการออกแบบนั้นมีจุดประสงค์เพื่อให้ง่ายต่อการจัดทำเอกสารรวมถึงแนวคิดของโฟลว์การเขียนโปรแกรม ไปข้างหน้า แนวคิดของการแบ่งปัญหาออกเป็นปัญหาประโยคเล็ก ๆ ดูเหมือนจะเป็นแนวคิดที่ยอดเยี่ยมจริงๆ มันจะช่วยลดความเข้าใจในการไหลของโปรแกรม ผลที่ตามมาของวิธีการออกแบบความรู้ก็คือจำนวนฟังก์ชั่นที่ต้องการจะถูก จำกัด ด้วยจินตนาการของโปรแกรมเมอร์ แทนที่จะกำหนดฟังก์ชั่นสำหรับงานบางอย่างมันสามารถสร้างเป็นscrapในวิธีการรู้หนังสือ สิ่งนี้จะทำให้การแทรกโค้ดโดยอัตโนมัติแทนที่จะเป็นการรวบรวมฟังก์ชั่นแยกต่างหากและความต้องการที่ตามมาของขั้นตอนการปรับการคอมไพล์ระหว่างขั้นตอนเพื่อให้ได้ความเร็วที่เท่าเทียมกัน ในความเป็นจริงความพยายามครั้งแรกของ Donald E. Knuthแสดงให้เห็นว่ามีเวลาดำเนินการที่ต่ำกว่าเนื่องจากความเป็นจริงนี้ ฉันรู้ว่าคอมไพเลอร์สามารถทำสิ่งนี้ได้มากมาย แต่นี่ไม่ใช่ความกังวลของฉัน ดังนั้นฉันจึงต้องการรับข้อเสนอแนะว่าทำไมจึงควรพิจารณาวิธีการออกแบบที่ไม่ดี / ดี?

3
รูปแบบการสังเกตการณ์; รู้ว่า * อะไร * เปลี่ยนไป?
ฉันได้สร้างคลาสนามธรรมสองวิชาและผู้สังเกตการณ์ที่กำหนดอินเทอร์เฟซรูปแบบการสังเกตคลาสสิก ฉันสืบทอดมาจากพวกเขาเพื่อใช้รูปแบบการสังเกตการณ์ ผู้สังเกตการณ์อาจมีลักษณะเช่นนี้: void MyClass::Update(Subject *subject) { if(subject == myService_) { DoSomething(); } else if(subject == myOtherService_) { DoSomethingElse(); } } นี่เป็นเรื่องปกติและบอกฉันว่าใครเปลี่ยนอะไร อย่างไรก็ตามมันไม่ได้บอกฉันว่ามีอะไรเปลี่ยนแปลง บางครั้งสิ่งนี้ก็โอเคเพราะฉันแค่จะสืบค้นเรื่องสำหรับข้อมูลล่าสุด แต่บางครั้งฉันก็ต้องรู้ว่าสิ่งที่เปลี่ยนแปลงไปในเรื่องนั้น ๆ ฉันสังเกตเห็นใน Java พวกเขามีทั้ง informObservers () วิธีการและalertObservers (Object ARG)วิธีการสันนิษฐานว่าจะระบุรายละเอียดเกี่ยวกับสิ่งที่เปลี่ยนแปลง ในกรณีของฉันฉันจำเป็นต้องรู้ว่าหนึ่งในสองของการกระทำที่แตกต่างกันเกิดขึ้นในเรื่องและถ้าเป็นการกระทำที่เฉพาะเจาะจงเพื่อทราบจำนวนเต็มที่เกี่ยวข้องกับการกระทำนั้น ดังนั้นคำถามของฉันคือ: วิธี C ++ ผ่านอาร์กิวเมนต์ทั่วไป (เช่น Java) ผู้สังเกตการณ์เป็นแบบแผนที่ดีที่สุดหรือไม่? บางทีระบบเหตุการณ์บางอย่าง? UPDATE ผมพบว่าบทความนี้ซึ่งพูดเกี่ยวกับรูปแบบ templating สังเกตการณ์: การนำเรื่องรูปแบบกับแม่แบบ / …

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

2
รูปแบบการออกแบบ GOF ใดที่มีการใช้งานแล้วเป็นคุณสมบัติภาษาชั้นหนึ่งใน C #?
(คำถามนี้ถูกปิดใน Stack Overflow เนื่องจากเป็น "กว้างเกินไป" และ "ไม่ใช่คำถามจริง" ดังนั้นอาจเหมาะสมกว่าหรือไม่) แรงบันดาลใจจากคำถามนี้ เรารู้ว่าเหตุการณ์ต่าง ๆ เป็นการนำภาษาไปใช้ในรูปแบบของผู้สังเกตการณ์ มีรูปแบบการออกแบบอื่น ๆ ที่ใช้งานเป็นภาษาใน C # หรือไม่ ฉันต้องการเก็บคำถามนี้ C # - เฉพาะเพราะมีรูปแบบการออกแบบจำนวนมากถูกนำไปใช้ในภาษาอื่นและฉันต้องการรักษาจุดเน้นนี้ ฉันไม่ได้มองหาการปรับใช้รูปแบบใน BCL (เช่นมัณฑนากรในคลาส WCF หรือวิธีการของโรงงานWebClient) แต่เป็นรูปแบบระดับภาษา จนถึงตอนนี้ฉันตระหนักถึงผู้สังเกตการณ์ ( event) และตัววนซ้ำ ( foreachเมื่อรวมกับคลาสและอินเตอร์เฟส BCL จำนวนมาก) อาจมีสิ่งที่ชัดเจนอื่น ๆ ที่ฉันหายไป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.