Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

นี่คือโพสต์ที่แปลด้วย AI

제이온

[Effective Java] รายการที่ 2. พิจารณาตัวสร้างหากมีพารามิเตอร์มากมาย

เลือกภาษา

  • ไทย
  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar

สรุปโดย AI ของ durumis

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

รูปแบบตัวสร้างแบบลำดับชั้น

ทั้งโรงงานแบบคงที่และตัวสร้างมีปัญหาในการจัดการกับพารามิเตอร์จำนวนมากอย่างเหมาะสม ตัวอย่างเช่น หากคลาสมี 6 ฟิลด์ และคุณต้องการแบ่งตัวสร้างออกเป็นกรณีที่มี 2 พารามิเตอร์ 3 พารามิเตอร์ ... เป็นต้น คุณสามารถใช้รูปแบบตัวสร้างแบบลำดับชั้น ดังที่แสดงด้านล่าง


public class NutritionFacts {

    private final int servingSize;

    private final int servings;

    private final int calories;

    private final int fat;

    private final int sodium;

    private final int carbohydrate;

    public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
        this.servingSize = servingSize;
        this.servings = servings;
        this.calories = calories;
        this.fat = fat;
        this.sodium = sodium;
        this.carbohydrate = carbohydrate;
    }

    public NutritionFacts(int servingSize, int servings) {
        this(servingSize, servings, 0, 0, 0, 0);
    }

    public NutritionFacts(int servingSize, int servings, int calories) {
        this(servingSize, servings, calories, 0, 0, 0);
    }

    public NutritionFacts(int servingSize, int servings, int calories, int fat) {
        this(servingSize, servings, calories, fat, 0, 0);
    }

    public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium) {
        this(servingSize, servings, calories, fat, sodium, 0);
    }


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


รูปแบบ JavaBeans

รูปแบบ JavaBeans คือการสร้างวัตถุโดยใช้ตัวสร้างที่ไม่มีพารามิเตอร์และเรียกใช้เมธอด setter เพื่อตั้งค่าค่าของพารามิเตอร์ ที่ต้องการ


public class NutritionFactsWithJavaBeansPattern {

    private int servingSize = -1; // จำเป็น  ไม่มีค่าเริ่มต้น

    private int servings = -1; // จำเป็น  ไม่มีค่าเริ่มต้น

    private int calories;

    private int fat;

    private int sodium;

    private int carbohydrate;

    public void setServingSize(int servingSize) {
        this.servingSize = servingSize;
    }

    public void setServings(int servings) {
        this.servings = servings;
    }

    public void setCalories(int calories) {
        this.calories = calories;
    }

    public void setFat(int fat) {
        this.fat = fat;
    }

    public void setSodium(int sodium) {
        this.sodium = sodium;
    }

    public void setCarbohydrate(int carbohydrate) {
        this.carbohydrate = carbohydrate;
    }


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


รูปแบบตัวสร้าง

รูปแบบตัวสร้างมักจะใช้เป็นการผสมผสานระหว่างความเสถียรของรูปแบบตัวสร้างแบบลำดับชั้นและความสามารถในการอ่าน ของรูปแบบ JavaBeans

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


public class NutritionFactsWithBuilderPattern {

    private final int servingSize;

    private final int servings;

    private final int calories;

    private final int fat;

    private final int sodium;

    private final int carbohydrate;

    private NutritionFactsWithBuilderPattern(Builder builder) {
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        fat = builder.fat;
        sodium = builder.sodium;
        carbohydrate = builder.carbohydrate;
    }

    public static class Builder {

        private final int servingSize;

        private final int servings;

        private int calories;

        private int fat;

        private int sodium;

        private int carbohydrate;

        public Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings = servings;
        }

        public Builder calories(int val) {
            calories = val;
            return this;
        }

        public Builder fat(int val) {
            fat = val;
            return this;
        }

        public Builder sodium(int val) {
            sodium = val;
            return this;
        }

        public Builder carbohydrate(int val) {
            calories = val;
            return this;
        }

        public NutritionFactsWithBuilderPattern build() {
            return new NutritionFactsWithBuilderPattern(this);
        }
    }


ตัวสร้างภายในคลาส Builder จะรับเฉพาะพารามิเตอร์ที่จำเป็นเท่านั้น และพารามิเตอร์แบบเลือกจะถูกเติมด้วยเมธอด setter แบบหนึ่ง จากนั้น NutritionFactsWithBuilderPattern วัตถุที่เสร็จสมบูรณ์จะถูกสร้างขึ้นโดยใช้เมธอด build() NutritionFactsWithBuilderPattern คลาสเป็นแบบไม่เปลี่ยนแปลง และเนื่องจากเมธอด setter ของตัวสร้างจะส่งคืนตัวสร้าง เอง จึงสามารถเรียกใช้แบบเชื่อมโยงกันได้ วิธีนี้เรียกว่า fluent API หรือ method chaining


NutritionFactsWithBuilderPattern nutritionFacts = 
    new NutritionFactsWithBuilderPattern.Builder(240, 8)
        .calories(100)
        .sodium(35)


สำหรับไคลเอ็นต์ รูปแบบตัวสร้างช่วยให้คุณเขียนและอ่านรหัสได้ง่าย


รูปแบบตัวสร้างทำงานได้ดีกับคลาสที่ออกแบบตามลำดับชั้น

public abstract class Pizza {

    public enum Topping {
        HAM, MUSHROOM, ONION, PEPPER, SAUSAGE
    }

    final Set toppings;

    Pizza(Builder builder) {
        toppings = builder.toppings.clone();
    }

    abstract static class Builder> {

        private EnumSet toppings = EnumSet.noneOf(Topping.class);

        public T addTopping(Topping topping) {
            toppings.add(topping);
            return self();
        }

        abstract Pizza build();

        protected abstract T self();
    }


Pizza.Builder คลาสเป็นประเภททั่วไปที่ใช้การจำกัดประเภทแบบวนซ้ำและใช้เมธอด self() แบบนามธรรมเพื่อให้การสนับสนุน method chaining โดยไม่ต้องแปลงประเภทในคลาสย่อย คลาสย่อยควรส่งคืนค่าของเมธอดนามธรรมนี้ให้เป็นตัวมันเอง

ตอนนี้ ลองมาดูคลาสย่อยของ Pizza นั่นคือ พิซซ่าแบบนิวยอร์กและพิซซ่าแบบ Calzone และสัมผัสกับความยืดหยุ่นของรูปแบบตัวสร้าง


public class NyPizza extends Pizza {

    public enum Size {
        SMALL, MEDIUM, LARGE
    }

    private final Size size; // พารามิเตอร์ที่จำเป็น

    private NyPizza(Builder builder) {
        super(builder);
        size = builder.size;
    }

    public static class Builder extends Pizza.Builder {

        private final Size size;

        public Builder(Size size) {
            this.size = size;
        }

        @Override
        NyPizza build() {
            return new NyPizza(this);
        }

        @Override
        protected Builder self() {
            return this;
        }
    }

}

public class CalzonePizza extends Pizza {

    private final boolean sauceInside; // พารามิเตอร์แบบเลือก

    private CalzonePizza(Builder builder) {
        super(builder);
        sauceInside = builder.sauceInside;
    }

    public static class Builder extends Pizza.Builder {

        private boolean sauceInside = false;

        public Builder sauceInside() {
            sauceInside = true;
            return this;
        }

        @Override
        CalzonePizza build() {
            return new CalzonePizza(this);
        }

        @Override
        protected Builder self() {
            return this;
        }
    }


เมธอด build() ที่กำหนดไว้ในตัวสร้างของแต่ละคลาสย่อยจะส่งคืนคลาสย่อยที่เฉพาะเจาะจง ฟังก์ชันที่เมธอดของคลาสย่อยจะส่งคืน ประเภทย่อยแทนที่จะเป็นประเภทของเมธอดของคลาสระดับบนเรียกว่า covariant return typing โดยใช้ฟังก์ชันนี้ ไคลเอ็นต์ ไม่จำเป็นต้องแปลงประเภท


NyPizza nyPizza = new NyPizza.Builder(Size.SMALL)
    .addTopping(Topping.SAUSAGE)
    .addTopping(Topping.ONION)
    .build();

CalzonePizza calzonePizza = new CalzonePizza.Builder()
    .addTopping(Topping.HAM)
    .sauceInside()


สำหรับไคลเอ็นต์ สามารถใช้ enum ของ Pizza และ enum ของแต่ละคลาสย่อยร่วมกันได้ และสร้างวัตถุให้สมบูรณ์โดยใช้ เมธอดที่เหมาะสม


ข้อเสียของรูปแบบตัวสร้าง

  • คุณต้องสร้างวัตถุตัวสร้าง
  • รหัสมีขนาดใหญ่


สรุป

หากตัวสร้างหรือเมธอดโรงงานแบบคงที่ต้องจัดการกับพารามิเตอร์จำนวนมาก ให้พิจารณาใช้รูปแบบตัวสร้าง


แหล่งที่มา

  • Effective Java
제이온
제이온
제이온
제이온
[Effective Java] รายการ 6. หลีกเลี่ยงการสร้างอ็อบเจ็กต์ที่ไม่จำเป็น คู่มือเกี่ยวกับวิธีลดการสร้างอ็อบเจ็กต์ที่ไม่จำเป็นใน Java อ็อบเจ็กต์แบบไม่เปลี่ยนแปลง เช่น String, Boolean ควรใช้ลิเทอรัล และควรแคชอินสแตนซ์ Pattern สำหรับนิพจน์ทั่วไป นอกจากนี้ การออโต้บอกซ์อาจทำให้ประสิทธิภาพลดลง ดังนั้นจึงควรใช้ประเภทพื้นฐาน รายละเอีย

28 เมษายน 2567

[Effective Java] รายการ 4. ใช้ตัวสร้างส่วนตัวเพื่อป้องกันการสร้างอินสแตนซ์ สำหรับคลาสยูทิลิตี้ที่มีเพียงเมธอดคงที่และฟิลด์ ควรตั้งค่าตัวสร้างให้เป็นส่วนตัวเพื่อป้องกันการสร้างอินสแตนซ์ วิธีนี้จะช่วยป้องกันผู้ใช้จากการเข้าใจผิดว่าตัวสร้างถูกสร้างขึ้นโดยอัตโนมัติ และทำให้ไม่สามารถสืบทอดได้ ทำให้ความตั้งใจของคลาสชัดเจนขึ้น

28 เมษายน 2567

[Java] แนวคิด Reflection และวิธีการใช้งาน Reflection เป็น API ที่ช่วยให้โปรแกรม Java สามารถเข้าถึงข้อมูลเกี่ยวกับคลาสในขณะที่โปรแกรมกำลังทำงาน และสามารถจัดการกับคลาสนั้นได้ API นี้สามารถสร้างคลาสใหม่และเข้าถึงฟิลด์และเมธอดได้ในขณะรันไทม์ แต่ควรใช้ด้วยความระมัดระวังเนื่องจากอาจส่งผลต่อการปิดบังข้อ

25 เมษายน 2567

การสร้างแบบจำลองข้อมูลเชิงแนวคิด การสร้างแบบจำลองข้อมูลเชิงแนวคิดเป็นกระบวนการแยกเอนทิตีและแสดงความสัมพันธ์ระหว่างเอนทิตีในรูปแบบ ERD เอนทิตีเป็นหน่วยข้อมูลอิสระ และแอตทริบิวต์คือข้อมูลที่เอนทิตีมี ตัวระบุคือสิ่งที่ระบุเอนทิตีเฉพาะและความสัมพันธ์แสดงถึงการโต้ตอบระหว่างเอนทิตี คาร์ดินัลลิ
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

8 เมษายน 2567

[Javascript] โครงสร้างของวัตถุ (V8) วัตถุของ JavaScript ในเครื่องยนต์ V8 ถูกแปลงเป็น Fast mode ที่ปรับให้เหมาะสมเหมือนโครงสร้างข้อมูลตามสถานะและ Dictionary mode ที่ทำงานเป็นแฮชแมป Fast mode เร็วเนื่องจากคีย์และค่าอยู่ในรูปแบบคงที่เกือบทั้งหมด แต่เมื่อมีการเพิ่มคีย์ใหม่หรือดำเนินการลบองค์ประ
곽경직
곽경직
곽경직
곽경직
곽경직

18 มีนาคม 2567

[นอกสายงาน วิศวกรซอฟต์แวร์อยู่รอด] 7. สิ่งที่ช่วยและไม่ช่วยในงานใหม่ ในการเตรียมตัวหางานวิศวกรซอฟต์แวร์ บล็อกเทคนิคอาจไม่มีประสิทธิภาพ แต่ GitHub แนะนำสำหรับการจัดการโครงการและการแชร์ซอร์สโค้ด หลายใบรับรอง ควรเตรียมใบรับรองวิชาชีพด้านสารสนเทศเป็นหลัก และขึ้นอยู่กับวุฒิการศึกษา ควรเลือกใบรับรองช่างฝีมือ ช่างเทคนิค หรือวิศวก
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

29 มีนาคม 2567

[ไม่มีพื้นฐานด้านวิทยาการคอมพิวเตอร์ ผู้พัฒนาอยู่รอดได้อย่างไร] 16. เคล็ดลับการสร้างพอร์ตโฟลิโอสำหรับนักพัฒนาใหม่ นักพัฒนาใหม่ (โดยเฉพาะผู้ที่ไม่มีพื้นฐานด้านวิทยาการคอมพิวเตอร์) ควรอธิบายบริการหรือฟังก์ชันที่พัฒนาขึ้นอย่างชัดเจนในระหว่างการสร้างพอร์ตโฟลิโอ ตัวอย่างเช่น โครงการ "ชุมชนสำหรับผู้สมัครงาน" หากเป็นโครงการ ควรระบุรายละเอียดของงาน เช่น กระดานถามตอบ ระบบการค
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 เมษายน 2567

[เรื่องราวของนักพัฒนา SI] 09. การเริ่มต้นการพัฒนาอย่างจริงจังหลังจากการเข้าร่วมโครงการ SI นักพัฒนา SI จะพัฒนาฟังก์ชันที่ระบุไว้ใน RFP หลังจากเข้าร่วมโครงการ แต่เนื่องจากข้อกำหนดเพิ่มเติมของลูกค้าทำให้มีการเปลี่ยนแปลงโค้ดบ่อย ทำให้ความสำคัญอยู่ที่การพัฒนาที่รวดเร็วมากกว่าประสิทธิภาพ ดังนั้นการพัฒนาควรเน้นที่การใช้งานมากกว่าการเขียนโค้ดที่สะอาดห
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

18 เมษายน 2567

การสร้างแบบจำลองข้อมูลเชิงกายภาพ การสร้างแบบจำลองข้อมูลเชิงกายภาพคือกระบวนการออกแบบตารางฐานข้อมูลเชิงสัมพันธ์เพื่อให้สามารถใช้งานได้จริง โดยมีเป้าหมายเพื่อเพิ่มประสิทธิภาพ โดยการพิจารณาประสิทธิภาพในการใช้พื้นที่จัดเก็บ การแบ่งพาร์ติชันข้อมูล การออกแบบดัชนี เป็นต้น สามารถแก้ไขปัญหาประสิทธ
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

9 เมษายน 2567