기술나눔

디자인 패턴 팩토리 패턴

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

팩토리 패턴(Factory Pattern)은 객체지향 프로그래밍에서 흔히 사용되는 디자인 패턴에 속합니다.창조 패턴 거의.팩토리 패턴은 주로 객체를 생성하는 데 사용되지만 코드에서 직접 사용하는 것과는 다릅니다.new 키워드 생성은 공통 인터페이스를 통해 개체를 생성하므로 개체 생성 프로세스와 클라이언트 코드 사용을 분리한다는 점에서 다릅니다. 다음은 팩토리 패턴에 대한 자세한 소개입니다.

1. 공장모델의 주요특징

  1. 캡슐화된 객체의 생성 과정: 객체 생성 프로세스를 팩토리 클래스에 캡슐화합니다. 클라이언트는 생성해야 하는 객체의 유형만 지정하면 객체의 특정 생성 세부 정보에 신경 쓰지 않고 팩토리 클래스를 통해 필요한 객체를 얻을 수 있습니다.
  2. 결합 감소: 추상 팩토리와 콘크리트 팩토리를 분리함으로써 클라이언트와 객체 간의 결합이 줄어들어 클라이언트 프로그램의 확장 및 유지 관리가 더 쉬워집니다.
  3. 프로그램 확장성 향상: 새 제품을 추가해야 할 경우 해당 특정 제품 클래스와 해당 공장 클래스만 추가하면 됩니다. 원래 코드를 수정할 필요가 없습니다. 개방형 폐쇄 원칙을 준수합니다. 수정을 위해) 코드의 확장성을 향상시킵니다.
  4. 유지 관리 및 업그레이드가 쉽습니다.: 팩토리 메소드는 객체를 생성하는 과정을 하나의 클래스에 집중시키기 때문에 객체 생성 방법을 수정해야 하는 경우 해당 팩토리 클래스만 수정하면 되며 클라이언트에는 아무런 영향을 미치지 않습니다.
  5. 코드 재사용: 팩토리 패턴은 객체 생성 프로세스를 추상화하고 코드 재사용을 실현하며 코드의 유연성과 재사용성을 높일 수 있습니다.

2. 공장 모델의 분류

팩토리 패턴은 크게 단순 팩토리 패턴(정적 팩토리 패턴), 팩토리 메소드 패턴, 추상 팩토리 패턴의 세 가지 유형으로 구분됩니다.

1. 정적 팩토리 메소드
  1. 전달된 다양한 매개변수를 기반으로 다양한 클래스의 인스턴스를 반환하도록 팩토리 클래스를 정의합니다.
  2. 팩토리 클래스에는 일반적으로 여러 정적 메서드가 포함되어 있으며 각 메서드는 특정 제품 생성에 해당합니다.
  3. 장점: 구현이 간단하고 이해하기 쉽습니다.
  4. 단점: 팩토리 클래스의 책임이 너무 무겁습니다. 새 제품을 추가할 때 팩토리 클래스의 소스 코드를 수정해야 하므로 열기 및 닫기 원칙에 위배됩니다.

간단한 팩토리 패턴 클래스 다이어그램

2. 팩토리 메소드 패턴(Factory Method)
  1. 객체 생성을 위한 인터페이스(추상 팩토리)를 정의하고,하지만 인스턴스화할 클래스를 하위 클래스가 결정하게 하세요.
  2. 팩토리 메소드를 사용하면 클래스 인스턴스화를 하위 클래스로 연기할 수 있습니다.
  3. 장점: 확장성이 좋습니다. 새로운 제품을 추가해야 하는 경우 해당하는 특정 제품 카테고리와 특정 공장 카테고리만 추가하면 됩니다.
  4. 단점: 제품이 추가될 때마다 특정 클래스와 객체 구현 팩토리를 추가해야 하므로 시스템의 클래스 수가 두 배로 늘어나고 시스템의 복잡성이 증가합니다.

팩토리 메소드 패턴

3. 추상 팩토리 패턴(Abstract Factory)
  1. 구체적인 클래스를 지정하지 않고 일련의 관련되거나 상호 의존적인 개체를 생성하기 위한 인터페이스를 제공합니다.
  2. 추상 팩토리 패턴은 여러 팩토리 메소드 패턴을 공동으로 사용하는 것으로 볼 수 있습니다.
  3. 장점: 제품군은 클래스 내에서 제한될 수 있습니다. 특정 공장에서는 제품군의 모든 제품을 생산할 수 있어야 합니다.
  4. 단점: 추상화와 시스템 이해의 어려움이 증가하고 시스템의 클래스 수가 크게 늘어납니다.

추상 공장 패턴

3. 공장 모델의 적용 시나리오

팩토리 패턴에는 데이터베이스 연결, UI 제어, 파일 처리, 로깅, 네트워크 통신, 메시지 대기열, 데이터 구조, 암호화 및 암호 해독, 메시지 푸시 및 작업 예약과 같은 실제 개발의 광범위한 응용 프로그램이 있습니다. 이러한 시나리오에서 팩토리 패턴을 사용하면 객체 생성 프로세스를 사용 프로세스에서 분리하여 시스템의 유연성과 확장성을 향상시킬 수 있습니다.

4. 공장 모델 예시

1. 간단한 팩토리 패턴 예시

간단한 팩토리 패턴에서는 전달된 매개변수에 따라 다양한 유형의 인스턴스를 반환할 수 있는 팩토리 클래스를 정의합니다.

다음은 Java로 작성된 간단한 팩토리 패턴의 예입니다. 원, 직사각형, 정사각형의 인스턴스를 생성할 수 있는 모양 팩토리를 만들어 보겠습니다. 먼저, 모양 인터페이스(Shape)와 이 인터페이스를 구현하는 여러 구체적인 클래스(Circle, Rectangle, Square)를 정의합니다.

  1. // 形状接口
  2. interface Shape {
  3. void draw();
  4. }
  5. // 圆形类
  6. class Circle implements Shape {
  7. @Override
  8. public void draw() {
  9. System.out.println("Inside Circle::draw() method.");
  10. }
  11. }
  12. // 矩形类
  13. class Rectangle implements Shape {
  14. @Override
  15. public void draw() {
  16. System.out.println("Inside Rectangle::draw() method.");
  17. }
  18. }
  19. // 正方形类
  20. class Square implements Shape {
  21. @Override
  22. public void draw() {
  23. System.out.println("Inside Square::draw() method.");
  24. }
  25. }

다음으로 정적 메서드를 사용하여 모양 개체를 생성하는 팩토리 클래스(ShapeFactory)를 정의합니다.

  1. // 形状工厂类
  2. class ShapeFactory {
  3. // 使用 getShape 方法获取形状类型的对象
  4. public static Shape getShape(String shapeType){
  5. if(shapeType == null){
  6. return null;
  7. }
  8. if(shapeType.equalsIgnoreCase("CIRCLE")){
  9. return new Circle();
  10. } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
  11. return new Rectangle();
  12. } else if(shapeType.equalsIgnoreCase("SQUARE")){
  13. return new Square();
  14. }
  15. return null;
  16. }
  17. }

마지막으로, 팩토리 클래스를 사용하여 모양 개체를 가져오고 해당 클래스를 호출할 수 있습니다.draw방법.

  1. public class FactoryPatternDemo {
  2. public static void main(String[] args) {
  3. // 获取 Circle 的对象,并调用它的 draw 方法
  4. Shape shape1 = ShapeFactory.getShape("CIRCLE");
  5. shape1.draw();
  6. // 获取 Rectangle 的对象,并调用它的 draw 方法
  7. Shape shape2 = ShapeFactory.getShape("RECTANGLE");
  8. shape2.draw();
  9. // 获取 Square 的对象,并调用它的 draw 方法
  10. Shape shape3 = ShapeFactory.getShape("SQUARE");
  11. shape3.draw();
  12. }
  13. }

이 예에서는ShapeFactory클래스는 생성을 담당합니다.Shape 인터페이스의 인스턴스입니다.클라이언트 코드는 유형 정보(예: 문자열)를 전달하여 이를 수행합니다.ShapeFactory클래스의 정적 메소드getShape 원하는 모양의 인스턴스를 얻으려면. 이러한 방식으로 클라이언트는 특정 클래스의 구현에서 분리되고 열기 및 닫기 원칙을 준수합니다. 즉, 클라이언트 코드를 수정하지 않고도 새로운 모양 클래스를 확장할 수 있습니다. 그러나 단순 팩토리 패턴의 주요 단점은 새로운 제품군(예: 모양 외에 색상 등)으로 시스템을 확장해야 하는 경우 팩토리 클래스를 수정해야 한다는 점입니다. 이는 개방형 규칙의 일부를 위반합니다. -폐쇄 원칙. 이 경우 Factory Method 패턴이나 Abstract Factory 패턴을 사용하는 것이 좋습니다.

2. 팩토리 메소드 패턴 예시

여전히 예를 들어 형태를 취하고 엔지니어링 방법을 사용하여 만듭니다.

먼저 모양 인터페이스(제품)를 정의하고 세 가지 구현 클래스를 만듭니다.

  1. // 形状接口
  2. interface Shape {
  3. void draw();
  4. }
  5. // 圆形类
  6. class Circle implements Shape {
  7. @Override
  8. public void draw() {
  9. System.out.println("Inside Circle::draw() method.");
  10. }
  11. }
  12. // 矩形类
  13. class Rectangle implements Shape {
  14. @Override
  15. public void draw() {
  16. System.out.println("Inside Rectangle::draw() method.");
  17. }
  18. }
  19. // 正方形类
  20. class Square implements Shape {
  21. @Override
  22. public void draw() {
  23. System.out.println("Inside Square::draw() method.");
  24. }
  25. }

다음으로 생성자 인터페이스(Creator)와 구체적인 생성자(Concrete Creator)를 정의합니다.

  1. // 创建者接口
  2. interface ShapeFactory {
  3. Shape getShape(String shapeType);
  4. }
  5. // 具体创建者类
  6. class RectangleFactory implements ShapeFactory {
  7. @Override
  8. public Shape getShape(String shapeType) {
  9. if (shapeType == null) {
  10. return null;
  11. }
  12. if (shapeType.equalsIgnoreCase("RECTANGLE")) {
  13. return new Rectangle();
  14. }
  15. return null;
  16. }
  17. }
  18. class CircleFactory implements ShapeFactory {
  19. @Override
  20. public Shape getShape(String shapeType) {
  21. if (shapeType == null) {
  22. return null;
  23. }
  24. if (shapeType.equalsIgnoreCase("CIRCLE")) {
  25. return new Circle();
  26. }
  27. return null;
  28. }
  29. }
  30. class SquareFactory implements ShapeFactory {
  31. @Override
  32. public Shape getShape(String shapeType) {
  33. if (shapeType == null) {
  34. return null;
  35. }
  36. if (shapeType.equalsIgnoreCase("SQUARE")) {
  37. return new Square();
  38. }
  39. return null;
  40. }
  41. }

마지막으로 구체적인 생성자 클래스를 사용하여 모양 개체를 가져오고 해당 개체를 호출합니다.draw방법:

  1. public class FactoryMethodPatternDemo {
  2. public static void main(String[] args) {
  3. ShapeFactory shapeFactory = new CircleFactory();
  4. // 获取 Circle 的对象,并调用它的 draw 方法
  5. Shape shape1 = shapeFactory.getShape("CIRCLE");
  6. shape1.draw();
  7. // 使用 RectangleFactory 来获取 Rectangle 的对象
  8. shapeFactory = new RectangleFactory();
  9. Shape shape2 = shapeFactory.getShape("RECTANGLE");
  10. shape2.draw();
  11. // 使用 SquareFactory 来获取 Square 的对象
  12. shapeFactory = new SquareFactory();
  13. Shape shape3 = shapeFactory.getShape("SQUARE");
  14. shape3.draw();
  15. }
  16. }

이 예에서는각 모양 클래스에 해당하는 팩토리 클래스를 만듭니다. (실제 애플리케이션에는 각 제품 클래스에 대해 별도의 팩토리 클래스를 작성하지 않기 위해 구성 파일이나 리플렉션을 통해 일반적으로 보다 일반적인 팩토리 클래스 구조가 있습니다.) 이는 팩토리 메소드 패턴의 기본 원칙을 보여주는 데 도움이 됩니다.즉, 팩토리 하위 클래스가 인스턴스화할 클래스를 결정하도록 합니다. . 그러나 이 예의 간단한 경우에는 Simple Factory 패턴을 사용하거나 다른 디자인 패턴을 고려하여 코드 중복을 줄이는 것이 더 나을 수 있습니다.

3. 추상 팩토리 예시

이 예에서는 휴대폰을 예로 들어 휴대폰과 관련된 추상 제품(예: 화면, 배터리, 운영 체제 등)을 사용하고 이러한 인터페이스를 구현하기 위한 특정 제품 클래스를 만듭니다. 그런 다음 추상 팩토리 인터페이스와 구체적인 팩토리 클래스를 정의하여 이러한 제품을 생산할 수 있습니다. 다음은 Abstract Factory 패턴을 사용하여 휴대폰의 다양한 제조업체 및 모델에 대한 구성 요소(화면 및 배터리)를 생산하는 방법을 보여주는 간단한 예입니다.

먼저 제품 인터페이스와 특정 제품을 정의합니다.

  1. // 屏幕接口
  2. interface Screen {
  3. void display();
  4. }
  5. // 高端屏幕的实现
  6. class HighEndScreen implements Screen {
  7. @Override
  8. public void display() {
  9. System.out.println("显示高清屏幕");
  10. }
  11. }
  12. // 低端屏幕的实现
  13. class LowEndScreen implements Screen {
  14. @Override
  15. public void display() {
  16. System.out.println("显示普通屏幕");
  17. }
  18. }
  19. // 电池接口
  20. interface Battery {
  21. void charge();
  22. }
  23. // 高效电池的实现
  24. class HighEfficiencyBattery implements Battery {
  25. @Override
  26. public void charge() {
  27. System.out.println("快速充电");
  28. }
  29. }
  30. // 标准电池的实现
  31. class StandardBattery implements Battery {
  32. @Override
  33. public void charge() {
  34. System.out.println("标准充电");
  35. }
  36. }

다음으로 추상 팩토리 인터페이스와 구체적인 팩토리 클래스를 정의합니다.

  1. // 手机组件工厂接口
  2. interface PhoneFactory {
  3. Screen createScreen();
  4. Battery createBattery();
  5. }
  6. // 高端手机工厂
  7. class HighEndPhoneFactory implements PhoneFactory {
  8. @Override
  9. public Screen createScreen() {
  10. return new HighEndScreen();
  11. }
  12. @Override
  13. public Battery createBattery() {
  14. return new HighEfficiencyBattery();
  15. }
  16. }
  17. // 低端手机工厂
  18. class LowEndPhoneFactory implements PhoneFactory {
  19. @Override
  20. public Screen createScreen() {
  21. return new LowEndScreen();
  22. }
  23. @Override
  24. public Battery createBattery() {
  25. return new StandardBattery();
  26. }
  27. }

마지막으로 추상 팩토리를 사용하여 구체적인 제품 객체를 생성하는 클라이언트 코드는 다음과 같습니다.

  1. public class PhoneFactoryPatternDemo {
  2. public static void main(String[] args) {
  3. // 使用高端手机工厂
  4. PhoneFactory highEndFactory = new HighEndPhoneFactory();
  5. Screen highEndScreen = highEndFactory.createScreen();
  6. Battery highEndBattery = highEndFactory.createBattery();
  7. highEndScreen.display();
  8. highEndBattery.charge();
  9. // 使用低端手机工厂
  10. PhoneFactory lowEndFactory = new LowEndPhoneFactory();
  11. Screen lowEndScreen = lowEndFactory.createScreen();
  12. Battery lowEndBattery = lowEndFactory.createBattery();
  13. lowEndScreen.display();
  14. lowEndBattery.charge();
  15. }
  16. }

이 예에서는 각각 특정 유형의 화면과 배터리를 생산할 수 있는 두 개의 휴대폰 공장(고급형 및 저가형)을 정의합니다.클라이언트 코드는 추상 팩토리 인터페이스를 통해 특정 팩토리 클래스와 상호 작용하여 특정 제품 클래스로부터의 분리를 달성합니다. . 이런 방식으로 향후 새로운 휴대폰 유형(예: 중저가 휴대폰)을 추가해야 하는 경우 기존 클라이언트 코드를 수정하지 않고 새로운 제품 클래스와 해당 팩토리 클래스만 추가하면 됩니다.

5. 요약

팩토리 패턴은 매우 유용한 디자인 패턴이지만,객체 생성 프로세스를 캡슐화하고, 결합을 줄이고, 프로그램 확장성과 유지 관리 용이성을 향상시킵니다. , 소프트웨어 개발에 널리 사용되었습니다.그러나 그것은 또한 일부공장의 과도한 책임, 시스템 확장의 어려움 등 단점 . 따라서 실제 적용에서는 특정 시나리오와 요구 사항에 따라 절충과 선택을 해야 합니다.

팩토리 패턴(간단한 팩토리, 팩토리 메소드, 추상 팩토리)이 유용하다면 좋아요와 수집을 잊지 마세요.