๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Programming/Android

Builder Pattern ์‚ฌ์šฉํ•˜๊ธฐ (Kotlin/Java)

๐Ÿ’ญ ์„œ๋ก  (a.k.a. ์‚ฌ๋‹ด)


๋“œ๋””์–ด ๋‚ด๊ฐ€ ๋‹ค์‹œ '์ฝ”ํ‹€๋ฆฐ ๊ฐœ๋ฐœ์ž'๋ผ๋Š” ํƒ€์ดํ‹€์„ ๋˜์ฐพ์•˜๋‹ค ๐Ÿ˜ญ

์ž๋ฐ”์—์„œ ๋‹ค์‹œ ์ฝ”ํ‹€๋ฆฐ์œผ๋กœ ๋Œ์•„์˜ค๊ธฐ๊นŒ์ง€ ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ ธ๋‹ค... ๊ทธ๋ž˜์„œ ์žŠ์–ด๋ฒ„๋ฆฐ ๊ฒŒ ๋„ˆ๋ฌด๋‚˜๋„ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฑธ ์˜ฌ๋ ค? ์‹ถ์€ ๊ฒƒ๋„ ์˜ฌ๋ฆด ๊ฒƒ์ด๋‹ค. ๐Ÿ˜ค ๐Ÿ˜ค ๐Ÿ˜ค ๐Ÿ˜ค

 

Builder Pattern์ด๋ž€?


์ฐธ์กฐ๋ฅผ ํ•  ์ฑ…์ด ์—†์œผ๋ฏ€๋กœ ๋‹น๋‹นํ•˜๊ฒŒ ์œ„ํ‚ค ๋ฐฑ๊ณผ๋ฅผ ์ฒจ๋ถ€ํ•ด ๋ณธ๋‹ค.

๋นŒ๋” ํŒจํ„ด - ์œ„ํ‚ค๋ฐฑ๊ณผ, ์šฐ๋ฆฌ ๋ชจ๋‘์˜ ๋ฐฑ๊ณผ์‚ฌ์ „

 

Builder Pattern์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ์™€ ์˜ˆ


Builder Pattern์€ ์ฃผ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋งŽ์€ ๊ฐ’์„ ๋„˜๊ฒจ์ค˜์•ผ ํ•  ๊ฒฝ์šฐ(๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง)๋‚˜ ํ•„์ˆ˜๊ฐ€ ์•„๋‹Œ ๊ฐ’๋“ค์„ ์„ ํƒํ•ด์„œ ์ดˆ๊ธฐํ™” ํ•ด์ค˜์•ผ ํ•  ๊ฒฝ์šฐ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•œ๋‹ค. ์•ˆ๋“œ๋กœ์ด๋“œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ Builder Pattern์€ ๋‹ค์ด์–ผ๋กœ๊ทธ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŒ์—… ๋‹ค์ด์–ผ๋กœ๊ทธ์˜ ํ˜•ํƒœ๊ฐ€ ์ด๋ฏธ์ง€๊ฐ€ ๋“ค์–ด๊ฐˆ ๋•Œ๊ฐ€ ์žˆ๊ณ , ํ…์ŠคํŠธ๊ฐ€ ๋ณผ๋“œ ์ฒ˜๋ฆฌ๊ฐ€ ๋œ ํƒ€์ดํ‹€์ด ๋“ค์–ด๊ฐˆ ๋•Œ๋„ ์žˆ๊ณ , ๋ฒ„ํŠผ์ด ์–‘์ชฝ์œผ๋กœ ์žˆ์„ ๋•Œ๊ฐ€ ์žˆ๊ณ  ํ™•์ธ ๋ฒ„ํŠผ ํ•˜๋‚˜๊ฐ€ ์žˆ์„ ๋•Œ๊ฐ€ ์žˆ๋‹ค. ์ด๋Ÿฐ ํŒ์—…์ด ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๋‹ค์ด์–ผ๋กœ๊ทธ ํด๋ž˜์Šค๋ฅผ ๊ณ„์† ์ƒ์„ฑํ•œ๋‹ค๋ฉด ๊ด€๋ฆฌํ•˜๊ธฐ๊ฐ€ ํž˜๋“ค๋‹ค. ๊ฐ™์ด ์ž‘์—…ํ•˜๋Š” ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋‚ด๊ฐ€ ๋งŒ๋“ค์–ด ๋‘” ๋‹ค์ด์–ผ๋กœ๊ทธ๋ฅผ ๋ฐœ๊ตด(?)ํ•˜์ง€ ๋ชป ํ•˜๊ณ  ๋น„์Šทํ•œ ๋‹ค์ด์–ผ๋กœ๊ทธ ํด๋ž˜์Šค๋ฅผ ๋˜ ๋งŒ๋“ค์–ด, ๊ฒฐ๊ตญ ๊ฐ์ž ์ž๊ธฐ๊ฐ€ ๋งŒ๋“  ๋‹ค์ด์–ผ๋กœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค ๋‚˜์ค‘์—์„œ์•ผ ์Œ๋‘ฅ์ด ๋‹ค์ด์–ผ๋กœ๊ทธ์˜ ์กด์žฌ๋ฅผ ์•Œ๊ฒŒ ๋˜๋Š” ๋ถˆ์ƒ์‚ฌ๊ฐ€ ์ผ์–ด๋‚œ๋‹ค. ๊ทธ๋Ÿฐ ์ถœ์ƒ์˜ ๋น„๋ฐ€์€ ์ผ์–ด๋‚˜์ง€ ์•Š๋Š” ํŽธ์ด ์ข‹๋‹ค.

๊ทธ๋ž˜์„œ ์ฃผ๋กœ ๊ธฐ๋ณธ์ ์ธ ํ•œ ๋‹ค์ด์–ผ๋กœ๊ทธ๊ฐ€ ๋ฒ„ํŠผ ํ˜•ํƒœ, ์ด๋ฏธ์ง€ ์œ ๋ฌด, ํ…์ŠคํŠธ ์œ ๋ฌด ์ •๋„๋ฅผ ๋‹ค๋ฅด๊ฒŒ ๊ฐ–๋Š”๋‹ค๋ฉด (์ƒ‰์ƒ์ด๋‚˜ ํฐํŠธ ํฌ๊ธฐ ๊ฐ™์€ ์„ธ๋ถ€์ ์ธ ๋””์ž์ธ์ด ํ†ต์ผ๋˜์–ด ์žˆ๋‹ค๋Š” ๊ฐ€์ • ํ•˜์—) ๋‹ค์ด์–ผ๋กœ๊ทธ ํ•˜๋‚˜์— Builder Pattern์„ ์ ์šฉํ•ด ๊ทธ๋•Œ ๊ทธ๋•Œ ์˜ต์…˜ ๊ฐ’์„ ์ค˜์„œ ์ปค์Šคํ…€ ๋œ ๋‹ค์ด์–ผ๋กœ๊ทธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

Java๋กœ ๊ตฌํ˜„ํ•œ Builder Pattern


public class SampleJavaDialog extends Dialog {
    private Context mContext;
    private String leftBtnText;
    private String rightBtnText;
    private String contentText;

    private TextView tv_left_btn;
    private TextView tv_right_btn;
    private TextView tv_content;

    public SampleJavaDialog(Context context, Builder builder) {
        super(context);
        mContext = context;

        this.contentText = builder.contentText;
        this.rightBtnText = builder.rightBtnText;
        this.leftBtnText = builder.leftBtnText;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.dialog_sample);
        initView();
    }

    private void initView() {
        tv_left_btn = (TextView) findViewById(R.id.tv_left_btn);
        tv_right_btn = (TextView) findViewById(R.id.tv_right_btn);
        tv_content = (TextView) findViewById(R.id.tv_content);


        if (leftBtnText != null) {
            tv_left_btn.setText(leftBtnText);
            tv_left_btn.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    Toast.makeText(mContext, leftBtnText, Toast.LENGTH_SHORT).show();
                    dismiss();
                }
            });
        }

        if (rightBtnText != null) {
            tv_right_btn.setText(rightBtnText);
            tv_right_btn.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    Toast.makeText(mContext, rightBtnText, Toast.LENGTH_SHORT).show();
                    dismiss();
                }
            });
        }

        if (contentText != null) {
            tv_content.setText(contentText);
        }
    }

    public static class Builder {
        private String leftBtnText;
        private String rightBtnText;
        private String contentText;

        public Builder setLeftBtnText(String text) {
            leftBtnText = text;
            return this;
        }

        public Builder setRightBtnText(String text) {
            rightBtnText = text;
            return this;
        }

        public Builder setContentText(String text) {
            contentText = text;
            return this;
        }

        public SampleJavaDialog build(Context context) {
            return new SampleJavaDialog(context, this);
        }
    }
}

 

Kotlin์œผ๋กœ ๊ตฌํ˜„ํ•œ Builder Pattern


class SampleKotlinDialog(context: Context, private val builder : Builder) : Dialog(context) {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        requestWindowFeature(Window.FEATURE_NO_TITLE)
        setContentView(R.layout.dialog_sample)
        initView()
    }

    private fun initView() {
        builder.leftBtnText?.let {
            tv_left_btn.text = builder.leftBtnText
            tv_left_btn.setOnClickListener {
                Toast.makeText(context, builder.leftBtnText, Toast.LENGTH_SHORT).show()
                dismiss()
            }
        }

        builder.rightBtnText?.let {
            tv_right_btn.text = builder.rightBtnText
            tv_right_btn.setOnClickListener {
                Toast.makeText(context, builder.rightBtnText, Toast.LENGTH_SHORT).show()
                dismiss()
            }
        }

        builder.contentText?.let {
            tv_content.text = builder.contentText
            tv_content.setOnClickListener {
                Toast.makeText(context, builder.contentText, Toast.LENGTH_SHORT).show()
            }
        }
    }

    class Builder {
        var leftBtnText : String? = null
        var rightBtnText : String? = null
        var contentText : String? = null

        fun leftBtnText(text : String) = apply { this.leftBtnText = text }
        fun rightBtnText(text : String) = apply { this.rightBtnText = text}
        fun contentText(text : String) = apply { this.contentText = text}

        fun build(context : Context) = SampleKotlinDialog(context, this)
    }
}  

 

Sample Code


commelier/android-builder-pattern-example

์œ„ repository ์ƒ˜ํ”Œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค.

์ฐธ์กฐ


https://medium.com/google-developers/kotlin-ifying-a-builder-pattern-e5540c91bdbe

Kotlin-ifying a Builder Pattern