Java ที่มีประสิทธิภาพโดย Joshua Bloch: รายการที่ 1 - วิธีโรงงานแบบคงที่

ฉันกำลังอ่าน Effective Java โดย Joshua Bloch และฉันมีคำถามเกี่ยวกับ Item1 Static Factory Method

ข้อความอ้างอิง[Bloch, p.7]

อินเทอร์เฟซไม่มีวิธีการแบบคงที่ ดังนั้นตามแบบแผน วิธีการแบบคงที่ของโรงงานสำหรับอินเทอร์เฟซที่ชื่อ Type จะถูกใส่ไว้ในคลาสที่ไม่สามารถสร้างอินสแตนซ์ได้ชื่อ Types ตัวอย่างเช่น Java Collections Framework จัดเตรียมคอลเลกชันที่ไม่สามารถแก้ไขได้ คอลเลกชันที่ซิงโครไนซ์ และอื่นๆ ที่คล้ายคลึงกัน การใช้งานเกือบทั้งหมดเหล่านี้จะถูกส่งออกผ่านวิธีการแบบคงที่ของโรงงานในคลาสที่ไม่สามารถอินสแตนซ์เดียว (java.util.Collections) คลาสของวัตถุที่ส่งคืนทั้งหมดนั้นไม่ใช่แบบสาธารณะ

ตกลง. เมื่อดูซอร์สโค้ด ฉันเห็นอินเทอร์เฟซ java.util.Collection และคลาส java.util.Collections พร้อมตัวสร้างส่วนตัว (คลาสที่ไม่สามารถเริ่มต้นได้) และฉันเห็นว่าคอลเลกชันคลาสที่ไม่สามารถเริ่มต้นได้มีวิธีการแบบคงที่ทั้งหมด เหมือนกับที่โบลชพูด แต่ฉันไม่เห็นความเชื่อมโยงระหว่างทั้งสองคลาสดังที่ Bloch พูด

อินเทอร์เฟซไม่สามารถมีวิธีการแบบคงที่ ดังนั้นตามแบบแผน วิธีการแบบคงที่จากโรงงานสำหรับอินเทอร์เฟซที่ชื่อ Type จะถูกใส่ไว้ในคลาสที่ไม่สามารถสร้างอินสแตนซ์ได้ซึ่งมีชื่อว่า Types

  1. ใครสามารถชี้ให้เห็นชัดเจนให้ฉัน?

  2. เมื่อเขาพูดหมายความว่าอย่างไร

คลาสของออบเจ็กต์ที่ส่งคืนทั้งหมดไม่ใช่แบบสาธารณะ

นี่คือที่ที่ฉันได้รับแหล่งที่มาของจาวา: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Collection.java?av=f


person Thang Pham    schedule 25.05.2011    source แหล่งที่มา
comment
ดูเพิ่มเติมที่ Bloch, Item 1   -  person trashgod    schedule 26.05.2011
comment
อะไรก็ตามเกี่ยวกับ Bloch นั้นบวกหนึ่งอย่างสำหรับฉันตามค่าเริ่มต้น   -  person Thufir    schedule 01.09.2013


คำตอบ (5)


  1. อินเทอร์เฟซไม่มีวิธีการแบบคงที่ ดังนั้นตามแบบแผน วิธีการแบบคงที่จากโรงงานสำหรับอินเทอร์เฟซที่ชื่อ Type จะถูกใส่ไว้ในคลาสที่ไม่สามารถสร้างอินสแตนซ์ได้ชื่อว่า Types

    ประเด็นนี้เป็นเพียง พหูพจน์ 's' บน "Type[s]" ดังนั้นหากอินเทอร์เฟซของคุณถูกเรียกว่า Foo และคุณต้องการสร้างการใช้งานบางอย่างที่เรียกว่า MyFoo ดังนั้นโรงงานของคุณที่มีวิธีการสร้างอินสแตนซ์ควรถูกเรียกว่า Foos ตามแบบแผน

  2. คลาสของออบเจ็กต์ที่ส่งคืนทั้งหมดไม่ใช่แบบสาธารณะ

    ซึ่งหมายความว่าคลาสของอ็อบเจ็กต์ที่ส่งคืนจากวิธีการของโรงงานจะมีตัวแก้ไขการมองเห็นส่วนตัวหรือค่าเริ่มต้นเช่นเดียวกับใน private class MyFoo{} เพื่อไม่ให้อินสแตนซ์เหล่านั้นด้วยวิธีอื่นใดนอกจากวิธีการของโรงงาน เนื่องจากคุณไม่สามารถสร้างวัตถุโดยใช้ตัวดำเนินการ new จากคลาสส่วนตัวภายในหรือแพ็คเกจส่วนตัวที่อยู่นอกขอบเขต (สะท้อนกลับกัน)

e.g.:

 public interface Foo{ //interface without plural 's' (question 1)
     public void bar();
 }
 public abstract class Foos(){ // abstract factory with plural 's' (question 1)
    public static Foo createFoo(){
        return new MyFoo();
    }
    private class MyFoo implements Foo{ // a non visible implementation (question 2)
       public void bar(){}
    }
 }
person fasseg    schedule 25.05.2011
comment
คำอธิบายที่ดีเกี่ยวกับ 1 ฉันเข้าใจว่ามันต้องดีกว่านี้ ขอบคุณมาก. สำหรับ 2: การมีวัตถุที่ส่งคืนเป็นอินสแตนซ์ของคลาสส่วนตัวมีประโยชน์อย่างไร - person Thang Pham; 25.05.2011
comment
คุณสามารถสลับการใช้งานโดยไม่ต้องให้ผู้ใช้ API สังเกตเห็น เนื่องจากเขาไม่เคยสร้างหนึ่งในออบเจ็กต์ด้วยตัวเขาเองโดยใช้ new ดังนั้น หากคุณต้องการปรับใช้บางอย่างอีกครั้ง คุณสามารถสร้างรีลีสใหม่ได้โดยไม่ต้องเปลี่ยนแปลง API ใดๆ - person fasseg; 25.05.2011
comment
หืม ฉันพบว่าฉันต้องเพิ่มตัวแก้ไข 'คงที่' ให้กับคลาสภายใน MyFoo เพื่อที่จะคอมไพล์... ไม่เช่นนั้น ฉันจะได้รับข้อผิดพลาดที่ไม่มีอินสแตนซ์ที่ปิดล้อมของ Foos อยู่ ฉันทำอะไรผิดหรือเปล่า? - person Mats_SX; 20.01.2014
comment
@Mats_SX: ฉันเพิ่งอ่านอะไรบางอย่างเกี่ยวกับเรื่องนั้น javarevisited.blogspot.sg/2012/02/ โดยพื้นฐานแล้วก็คือในคลาส MyFoo ภายใน คุณได้ยกตัวอย่าง Foos และอ้างอิงมัน - person MacD; 09.02.2014
comment
ตัวอย่างที่ดีอย่างหนึ่งคือ Lists คลาสจาก Guava ซึ่งมีฟังก์ชันโรงงานแบบคงที่สำหรับ List อินสแตนซ์ ตัวอย่างเช่น คุณสามารถสร้างรายการสตริงด้วยโค้ดต่อไปนี้: List<String> list = Lists.newArrayList("first", "second", "third") - person pedromanoel; 13.03.2017

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

public class ListFactory{
  private ListFactory(){}
  public static List makeArrayList(){...}
  public static List makeLinkedList(){...}
  public static List makeCrazyList(){...}
}

คุณไม่สามารถทำเช่นนี้ได้

public interface List{
   public static List makeArrayList();
   public static List makeLinkedList();
   public static List makeCrazyList();
}

เนื่องจาก List เป็นอินเทอร์เฟซ

person Alvin    schedule 25.05.2011
comment
ตั้งแต่ Java 8 เป็นต้นไป ข้อจำกัดที่อินเทอร์เฟซไม่สามารถมีวิธีแบบคงที่ได้ถูกยกเลิกไปแล้ว - person Mohdroid; 26.04.2021

ยกตัวอย่าง Collections.unmodifiableList(...). มันส่งคืนการใช้งานบางอย่างของรายการ แต่ชื่อของคลาสการใช้งานนั้นไม่เกี่ยวข้อง นอกจากนี้ คลาสดังกล่าว เท่านั้น ถูกสร้างขึ้นโดยวิธีโรงงานแบบคงที่

person Dilum Ranatunga    schedule 25.05.2011

1) ฉันไม่เข้าใจคำถามของคุณที่นี่ Collection เป็นอินเทอร์เฟซและ Collections มีวิธีการบางอย่างจากโรงงานเช่น emptyList

2) เช่น List instance ที่ส่งคืนโดย Collection.emptyList เป็นอินสแตนซ์ของคลาสส่วนตัวที่ใช้อินเทอร์เฟซ List

person Kaj    schedule 25.05.2011
comment
ฉันมีคำถามอื่นสำหรับคุณ สำหรับ 2 การมีวัตถุที่ส่งคืนเป็นอินสแตนซ์ของคลาสส่วนตัวมีประโยชน์อย่างไร - person Thang Pham; 25.05.2011

มันหมายความว่าประเภทการส่งคืนของเมธอดโรงงานแบบคงที่ใน Collections (และคลาสอื่น ๆ ที่คล้ายกัน) เป็นประเภทอินเทอร์เฟซ (เช่น List) แทนที่จะเป็นคลาสการใช้งานเฉพาะ (เช่น java.util.Collections.UnmodifiableList) ซึ่งผู้ใช้จะมองไม่เห็นเนื่องจากจะทำให้สิ่งต่าง ๆ ซับซ้อนขึ้น และเพิ่มขนาดของ API

person ColinD    schedule 25.05.2011