>  기사  >  Java  >  Java 디자인 패턴의 빌더 패턴 및 프로토타입 패턴 소개(코드 예)

Java 디자인 패턴의 빌더 패턴 및 프로토타입 패턴 소개(코드 예)

不言
不言원래의
2018-09-12 15:58:442023검색

이 기사는 Java 디자인 패턴(코드 예제)의 빌더 패턴 및 프로토타입 패턴에 대한 소개를 제공합니다. 필요한 친구가 참고할 수 있기를 바랍니다.

머리말

이전 글에서는 팩토리 패턴에 대해 알아보고 간단한 팩토리 패턴, 팩토리 메소드, 추상 팩토리 패턴을 소개했습니다. 본 글에서는 디자인 패턴 중 창의적인 패턴인 빌더 패턴과 프로토타입 패턴을 소개합니다.

빌더 모드

소개

빌더 모드는 창의적인 모드입니다. 빌더 패턴은 여러 개의 단순 객체를 사용하여 복잡한 객체를 단계별로 구축합니다. 이러한 유형의 디자인 패턴은 객체를 생성하는 최적의 방법을 제공하는 생성 패턴입니다.
간단히 말하면 복잡한 것을 추출하여 외부 세계에 간단한 호출을 제공하는 것이며, 이는 동일한 구축 과정에서 다양한 표현을 생성할 수 있습니다. 공장 모드와 매우 유사하지만 구성 요소 조립에 더 많은 관심을 기울입니다.

다음은 설명을 위한 예입니다.
우리가 매일 먹는 음식에는 부침개, 도시락, 라면, 두유, 우유, 주스가 있습니다. 식사는 아침, 점심, 저녁 세 끼로 나누어집니다. 식사는 주로 음식(밥)과 음료(두유, 주스 등)로 이루어지며, 아침 식사로 팬케이크와 두유를 먹고 도시락도 먹을 수 있습니다. 그리고 주스를 점심으로 먹기 때문에 아침과 점심으로 무엇을 먹어야 할지 정확히 알 수 있습니다.

먼저 음식과 음료라는 두 가지 속성으로 음식 카테고리를 정의합니다.

class Meal{
    private String food;
    private String drinks;
    
    public String getFood() {
        return food;
    }
    public void setFood(String food) {
        this.food = food;
    }
    
    public String getDrinks() {
        return drinks;
    }
    public void setDrinks(String drinks) {
        this.drinks = drinks;
    }
}

음식을 정의할 때 음식에 대한 표준 인터페이스를 정의하는 것입니다. 실제로 음식을 먹고 마시는 것을 의미합니다.

interface IBuilderFood{
    void buildFood();
    void buildDrinks();
    Meal createMeal();
}

음식 인터페이스는 먹고 마시는 구성 요소를 정의한 다음 createMeal() 메서드를 통해 필요한 음식을 반환합니다.
이제 아침과 점심을 정의할 수 있습니다.
코드 예:

class Breakfast implements IBuilderFood{
    Meal meal;

    public Breakfast(){
        meal=new Meal();
    }
    
    @Override
    public void buildFood() {
        meal.setFood("煎饼");
    }

    @Override
    public void buildDrinks() {
        meal.setDrinks("豆浆");   
    }
    
    @Override
    public Meal createMeal() {
        return meal;
    }
}

class Lunch implements IBuilderFood{
    Meal meal;

    public Lunch(){
        meal=new Meal();
    }
    
    @Override
    public void buildFood() {
        meal.setFood("盒饭");
    }

    @Override
    public void buildDrinks() {
        meal.setDrinks("果汁");   
    }
    
    @Override
    public Meal createMeal() {
        return meal;
    }
}

정의하면 아침 식사와 점심 식사를 만드는 과정이 완료됩니다. 하지만 이것은 빌더 모드가 아닙니다. 복잡한 객체의 일부를 생성하거나, 부품을 완전히 생성하거나, 특정 규칙에 따라 생성하는 데 사용되는 핵심 디렉터가 있습니다. 이제 식사를 만들기 위한 Director를 만들 수 있습니다. 어떤 식사가 만들어지는지는 알 필요가 없으며 호출하는 사람이 결정합니다.

여기서 레스토랑을 정의하고 식사를 만들 수 있습니다. 고객이 어떤 식사를 만들 것인지 결정합니다.
코드 예:

class FoodStore{
    public Meal createBreakfast(IBuilderFood bf){
        bf.buildDrinks();
        bf.buildFood();
        return bf.createMeal();
    }
}

이 Director를 생성한 후 통화 테스트를 해보겠습니다.

코드 예:

public class BuilderTest {

    public static void main(String[] args) {
        FoodStore foodStore=new FoodStore();
        Meal meal=foodStore.createBreakfast(new Breakfast());
        Meal meal2=foodStore.createBreakfast(new Lunch());
        System.out.println("小明早上吃的是:"+meal.getFood()+",喝的饮料是:"+meal.getDrinks());
        System.out.println("小明中午吃的是:"+meal2.getFood()+",喝的饮料是:"+meal2.getDrinks()); 
    }

}

출력 결과:

小明早上吃的是:煎饼,喝的饮料是:豆浆
小明中午吃的是:盒饭,喝的饮料是:果汁

는 빌더 모드의 작동 원리를 간략하게 소개합니다. 이는 다음 4가지로 요약할 수 있습니다.

  1. Builder: 추상 인터페이스를 지정하고, 이 제품에 필요한 구성 요소 생성에는 특정 개체 구성 요소 생성이 포함되지 않습니다.

  2. ConcreteBuilder: Builder 인터페이스를 구현하고, 다양한 로직에 대해 다양한 메소드를 생성하고, 최종적으로 제품의 인스턴스를 제공하는 것이 필요합니다.

  3. 디렉터: 복잡한 개체의 일부를 만드는 데 사용됩니다. 이 부분을 완전히 만들거나 특정 규칙에 따라 만듭니다.

  4. 제품: 구성된 복합 개체를 나타냅니다.

사용 시나리오:
일부 기본 구성 요소가 불편할 때 적용 가능하지만 조합이 자주 변경됩니다. 예를 들어, 슈퍼마켓 판촉 선물 패키지입니다.

장점:

  1. 빌더 독립적이며 확장이 쉽습니다.

  2. 상세한 리스크 관리가 용이합니다.

단점

  1. 내부 구조가 복잡하고 이해하기 쉽지 않습니다.

  2. 제품에는 직접적인 공통점이 있어야 하며 범위는 통제되어야 합니다.

프로토타입 패턴

프로토타입 패턴은 성능을 보장하면서 반복되는 개체를 만드는 데 사용됩니다. 이러한 유형의 디자인 패턴은 객체를 생성하는 최적의 방법을 제공하는 생성 패턴입니다.

일반적으로 객체를 생성할 때는 직접 생성하지만 객체 생성 비용이 높을 경우 반복적인 2차 생성은 비용 효율적이지 않습니다.
예를 들어, 우리는 축제 기간 동안 모두 이메일을 보냈고, 이러한 축복은 이름을 제외하면 대부분 동일합니다. 현재 이 모드를 사용하여 그에 따라 생성할 수 있습니다.

다음은 설명하기 위한 간단한 예입니다.
샤오밍과 샤오홍의 생일이 같은 날이라 축하 메일을 보내야 하는데, 게을러서 이름 빼고는 축복의 말이 똑같네요. 이때 먼저 축복문 작성을 완료한 다음 축복문을 복제하고 마지막으로 다른 이름으로 보낼 수 있습니다. 하지만 여기서는 간단하게 설명하겠습니다. 인쇄해 보세요.

코드 예:

public class PrototypeTest {

    public static void main(String[] args) {
        Mail mail=new Mail();
        mail.setMsg("生日快乐!");
        Mail mail2=(Mail) mail.clone();
        mail.setName("小明");
        mail2.setName("小红");
        System.out.println(mail.toString());
        System.out.println(mail2.toString());
    }
}

 class Mail implements Cloneable {
    private String name;
    private String msg;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }

    @Override
    public String toString() {
        return name + ":" + msg ;
    }
    
}

출력 결과:

小明:生日快乐!
小红:生日快乐!

看完原型模式的创建,是不是感觉就是和Java中克隆即为类似呢?
实际上它的核心也就是克隆。
克隆有两种,浅克隆和深克隆,本文主要介绍的是浅克隆。
浅克隆:

在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。
简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。
实现Cloneable接口并重写Object类中的clone()方法;

深克隆:

在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。

简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。
实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。

使用场景:

  1. 类初始化的时候需要消耗大量资源的时候;

  2. 获取数据库连接繁琐的时候;

  3. 一个对象,有很多个修改者的时候;

优点:
1.可以提升性能;

缺点:
1.因为必须实现Cloneable 接口,所以用起来可能不太方便。

相关推荐:

Java设计模式中工厂模式的介绍(代码示例)

Java设计模式是什么?Java设计模式中单例模式的介绍

위 내용은 Java 디자인 패턴의 빌더 패턴 및 프로토타입 패턴 소개(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.