+2

Object oriented design pattern: Factory Method và Abstract Factory Method

Design Pattern là một kỹ thuật trong lập trình hướng đối tượng, được sử dụng thường xuyên trong các ngôn ngữ lập trình hướng đối tượng. Nó sẽ cung cấp cho bạn các "mẫu thiết kế", các giải pháp để giải quyết các vấn đề chung, thường gặp trong lập trình. Các vấn đề mà bạn gặp phải có thể bạn sẽ tự nghĩ ra cách giải quyết nhưng có thể nó chưa phải là tối ưu. Design Pattern giúp bạn giải quyết vấn đề một cách tối ưu nhất, cung cấp cho bạn các giải pháp trong lập trình hướng đối tượng.

Design Pattern có 3 nhóm bao gồm:

  • Creational Pattern (nhóm khởi tạo) gồm: Abstract Factory, Factory Method, Singleton, Builder, Prototype. Nó sẽ giúp bạn trong việc khởi tạo đối tượng. Như bạn biết để khởi tạo đối tượng bạn phải sử dụng từ khóa new, nhóm Creational Pattern sẽ sử dụng một số thủ thuật để khởi tạo đối tượng mà bạn sẽ không nhìn thấy từ khóa này.

  • Structural Pattern (nhóm cấu trúc) gồm: Adapter, Bridge, Composite, Decorator, Facade, Proxy, Flyweight. Được dùng để thiết lập, định nghĩa quan hệ giữa các đối tượng.

  • Behavioral Pattern gồm: Interpreter, Template Method, Chain of Responsibility, Command, Iterator, Mediator, Memento, Observer, State, Strategy và Visitor. Nhóm này dùng trong việc xử lý thực hiện các hành vi của đối tượng.

Hôm nay mình xin giới thiệu 2 Design Pattern đơn giản và hay được sử dụng nhất, đó là Factory Method và Abstract Factory. Chương trình demo sử dụng ngôn ngữ Java.

Factory Method

Đây là pattern có thể nói là được sử dụng phổ biến nhất, với mục đích sử dụng để quản lý và khởi tạo các đối tượng một cách linh hoạt. Hãy xem xét một ví dụ để có thể hiểu cách sử dụng pattern này dễ dàng hơn. Chúng ta cần xây dựng và quản lý các đối tượng hình học, tùy vào input mà sẽ tạo các đối tượng tương ứng. Từ bài toán đặt ra, đây là sơ đồ uml.

factory.png

Bước 1: Tạo Shape Interface

public interface Shape {
   void draw();
}

Bước 2: Triển khai Shape interface, tạo ra các đối tượng hình học cụ thể.

// Rectangle.java
public class Rectangle implements Shape {
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}
//
// Square.java
public class Square implements Shape {
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}
//
// Circle.java
public class Circle implements Shape {
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}

Bước 3: Xây dựng class Factory, tạo ra các đối tượng hình học theo input nhận được.

// ShapeFactory.java
public class ShapeFactory {
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
}

Bước 4: sử dụng factory đã xây dựng ở bước 3 để khởi tạo các đối tượng mong muốn.

// FactoryPatternDemo.java
public class FactoryPatternDemo {
   public static void main(String[] args) {
      ShapeFactory shapeFactory = new ShapeFactory();
      //Khởi tạo đối tượng.
      Shape circle = shapeFactory.getShape("CIRCLE");
      Shape rectangle = shapeFactory.getShape("RECTANGLE");
      Shape square = shapeFactory.getShape("SQUARE");
      //Gọi phương thức của đối tượng.
      circle.draw();
      rectangle.draw();
      square.draw();
   }
}

Kết quả:

Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.

Như vậy, chúng ta có thể thấy việc quản lý và khởi tạo đối tượng đều được thực hiện trong lớp ShapeFactory, giúp cho việc bảo trì và mở rộng dễ dàng hơn.

Abstract Factory

Mục đích: Cung cấp một cách hỗ trợ việc quản lý và tạo ra các đối tượng cùng nhóm. Như tên của pattern này thì nó giống như một nhà máy sản sinh ra các đối tượng.

Ví dụ: Xây dựng việc khởi tạo và quản lý các đối tượng hình học và màu sắc.

abs.png

Bước 1: Tạo interface Shape

// Shape.java
public interface Shape {
   void draw();
}

Bước 2: Triển khai Shape interface, xây dựng các đối tượng hình học cụ thể.

//Rectangle.java
public class Rectangle implements Shape {
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}
//
// Square.java
public class Square implements Shape {
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}
//
// Circle.java
public class Circle implements Shape {
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}

Bước 3: Tạo interface Color

// Color.java
public interface Color {
   void fill();
}

Bước 4: Triển khai Color interface, xây dựng các đối tượng vẽ màu cụ thể.

// Red.java
public class Red implements Color {
   @Override
   public void fill() {
      System.out.println("Inside Red::fill() method.");
   }
}
//
// Green.java
public class Green implements Color {
   @Override
   public void fill() {
      System.out.println("Inside Green::fill() method.");
   }
}
//
//Blue.java
public class Blue implements Color {
   @Override
   public void fill() {
      System.out.println("Inside Blue::fill() method.");
   }
}

Bước 5: Xây dựng abstract class khởi tạo các đối tượng Color và Shape.

//AbstractFactory.java
public abstract class AbstractFactory {
   abstract Color getColor(String color);
   abstract Shape getShape(String shape) ;
}

Bước 6: Triển khai abstract class vừa xây dựng ở bước 5.

// ShapeFactory.java
public class ShapeFactory extends AbstractFactory {
   @Override
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
   @Override
   Color getColor(String color) {
      return null;
   }
}
//
// ColorFactory.java
public class ColorFactory extends AbstractFactory {
   @Override
   public Shape getShape(String shapeType){
      return null;
   }
   @Override
   Color getColor(String color) {
      if(color == null){
         return null;
      }
      if(color.equalsIgnoreCase("RED")){
         return new Red();
      }else if(color.equalsIgnoreCase("GREEN")){
         return new Green();
      }else if(color.equalsIgnoreCase("BLUE")){
         return new Blue();
      }
      return null;
   }
}

Bước 7: Tạo Factory class, nhận nhiệm vụ khởi tạo các loại đối tượng mong muốn.

// FactoryProducer.java
public class FactoryProducer {
   public static AbstractFactory getFactory(String choice){
      if(choice.equalsIgnoreCase("SHAPE")){
         return new ShapeFactory();
      }else if(choice.equalsIgnoreCase("COLOR")){
         return new ColorFactory();
      }
      return null;
   }
}

Bước 8: Sử dụng Factory đã tạo ở bước 7 để khởi tạo các đối tượng.

// AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {
   public static void main(String[] args) {
      //Khởi tạo đối tượng xây dựng các object
      AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
      AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
      //Khởi tạo các object cụ thể
      Shape circle = shapeFactory.getShape("CIRCLE");
      Shape rectangle = shapeFactory.getShape("RECTANGLE");
      Shape square = shapeFactory.getShape("SQUARE");
      Color red = colorFactory.getColor("RED");
      Color green = colorFactory.getColor("Green");
      Color blue = colorFactory.getColor("BLUE");
      // Gọi các phương thức của object
      circle.draw();
      rectangle.draw();
      square.draw();
      red.fill();
      green.fill();
      blue.fill();
   }
}

Kết quả

Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.

Tham khảo: https://www.tutorialspoint.com/design_pattern/


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.