Phương pháp nhà máy tĩnh là gì?


261

Phương pháp "nhà máy tĩnh" là gì?


Một phương pháp nhà máy tĩnh thay thế là sử dụng tiêm phụ thuộc.
CMCDragonkai

1
@ThangPham Câu trả lời của Jason Owen là thiếu sót vì nó có ý định nói về mẫu Phương thức nhà máy, rất khác với mẫu phương pháp nhà máy tĩnh mà nó thực sự nói đến. Vì vậy, trong khi trả lời câu hỏi thực tế rất tốt, tôi không nghĩ nó có thể được chấp nhận ở trạng thái hiện tại, bởi vì nó mang một mô hình không liên quan và làm tăng sự nhầm lẫn cực kỳ phổ biến về sự khác biệt giữa hai mẫu.
Theodore Murdock

@CMCDragonkai Tôi nghĩ rằng tiêm phụ thuộc và nhà máy tĩnh là khác nhau. Nhà máy tĩnh có thể được yêu cầu ngay cả trong trường hợp tiêm phụ thuộc để khởi tạo phụ thuộc được tiêm.
Karan Khanna

Câu trả lời:


126

Chúng tôi tránh cung cấp quyền truy cập trực tiếp vào các kết nối cơ sở dữ liệu vì chúng chiếm nhiều tài nguyên. Vì vậy, chúng tôi sử dụng phương pháp nhà máy tĩnh getDbConnectiontạo kết nối nếu chúng tôi ở dưới giới hạn. Mặt khác, nó cố gắng cung cấp kết nối "dự phòng", không thành công nếu có ngoại lệ.

public class DbConnection{
   private static final int MAX_CONNS = 100;
   private static int totalConnections = 0;

   private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();

   private DbConnection(){
     // ...
     totalConnections++;
   }

   public static DbConnection getDbConnection(){

     if(totalConnections < MAX_CONNS){
       return new DbConnection();

     }else if(availableConnections.size() > 0){
         DbConnection dbc = availableConnections.iterator().next();
         availableConnections.remove(dbc);
         return dbc;

     }else {
         throw new NoDbConnections();
     }
   }

   public static void returnDbConnection(DbConnection dbc){
     availableConnections.add(dbc);
     //...
   }
}

nếu tôi hiểu đúng, bạn có thể thêm AvailableConnections.add (db) vào phương thức returnDbConnection (DbConnection db) không?
Haifeng Zhang

@haifzhan, nó không thực sự có ý định hoàn thành, nhưng không sao.
Matthew Flaschen

@MatthewFlaschen cũng nên giảm tổng số Kết nối trong khi kết nối được trả lại?
đá lăn

@Sridhar, không, đó là số lượng kết nối tồn tại (được theo dõi sao cho nhiều hơn MAX_CONNS không được tạo), không phải là số lượng đang lưu hành.
Matthew Flaschen

@MatthewFlaschen phương thức của bạn sẽ bị sonarcube bắt gặp là trình chặn lỗi nếu DbConnection có thể đóng được.
Awan Biru

477

Mẫu phương thức tĩnh của nhà máy là một cách để đóng gói việc tạo đối tượng. Nếu không có một phương pháp nhà máy, bạn chỉ cần gọi của lớp constructor trực tiếp: Foo x = new Foo(). Với mẫu này, thay vào đó bạn sẽ gọi phương thức xuất xưởng : Foo x = Foo.create(). Các constructor được đánh dấu là private, vì vậy chúng không thể được gọi ngoại trừ từ bên trong lớp và phương thức Factory được đánh dấu staticđể nó có thể được gọi mà không cần có đối tượng trước.

Có một vài lợi thế cho mẫu này. Một là nhà máy có thể chọn từ nhiều lớp con (hoặc người triển khai giao diện) và trả lại cái đó. Bằng cách này, người gọi có thể chỉ định hành vi mong muốn thông qua các tham số, mà không cần phải biết hoặc hiểu một hệ thống phân cấp lớp có khả năng phức tạp.

Một lợi thế khác là, như Matthew và James đã chỉ ra, kiểm soát truy cập vào một tài nguyên hạn chế như các kết nối. Đây là một cách để thực hiện các nhóm đối tượng có thể tái sử dụng - thay vì xây dựng, sử dụng và phá hủy một đối tượng, nếu việc xây dựng và phá hủy là các quy trình đắt tiền, có thể có ý nghĩa hơn khi xây dựng chúng một lần và tái chế chúng. Phương thức nhà máy có thể trả về một đối tượng được khởi tạo hiện tại, chưa sử dụng nếu nó có một đối tượng hoặc xây dựng một đối tượng nếu số lượng đối tượng nằm dưới ngưỡng thấp hơn hoặc ném ngoại lệ hoặc trả vềnull nếu vượt quá ngưỡng trên.

Theo bài viết trên Wikipedia, nhiều phương thức xuất xưởng cũng cho phép các cách hiểu khác nhau về các loại đối số tương tự. Thông thường hàm tạo có cùng tên với lớp, có nghĩa là bạn chỉ có thể có một hàm tạo với một chữ ký đã cho . Các nhà máy không bị ràng buộc quá nhiều, có nghĩa là bạn có thể có hai phương thức khác nhau chấp nhận cùng loại đối số:

Coordinate c = Coordinate.createFromCartesian(double x, double y)

Coordinate c = Coordinate.createFromPolar(double distance, double angle)

Điều này cũng có thể được sử dụng để cải thiện khả năng đọc, như Rasmus lưu ý.


32
Lưu ý rằng phương thức nhà máy tĩnh không giống với mẫu Phương thức nhà máy từ Mẫu thiết kế [Gamma95, p. 107]. Phương thức nhà máy tĩnh được mô tả trong mục này không có tương đương trực tiếp trong Mẫu thiết kế.
Josh Sunshine

Phần thưởng cho tôi trong câu trả lời này là tham chiếu đến các đối tượng có thể gộp chung. Đây là chính xác cách tôi đang sử dụng mẫu phương thức nhà máy. Các phương thức của nhà máy được cung cấp để giúp kiểm soát vòng đời của một đối tượng: "tạo" hoặc kéo một đối tượng khỏi nhóm hoặc tạo một thể hiện mới nếu nhóm đó trống, "hủy" trả nó về nhóm để sử dụng lại trong tương lai.
MutantXothy

2
Bạn thực sự nên sử dụng "mẫu phương thức nhà máy tĩnh" bất cứ nơi nào bạn nói "mẫu phương thức nhà máy" trong bài đăng này, bạn đang sử dụng thuật ngữ sai. Ngoài ra, bạn đang liên kết đến bài viết Wikipedia trên một mẫu khác với mẫu bạn đang nói đến. Mẫu Phương thức nhà máy có lẽ nên được gọi là mẫu "Giao diện nhà máy", vì nó liên quan đến việc sử dụng một số đối tượng nhà máy thực hiện giao diện nhà máy để cho phép một thuật toán duy nhất tạo ra cũng như làm việc với các phiên bản của giao diện, bằng cách chấp nhận một đối tượng nhà máy có thể tạo ra các lớp con mong muốn cụ thể.
Theodore Murdock

8
Tôi đồng ý với @TheodoreMurdock. Bạn đang sử dụng thuật ngữ sai. Những gì bạn đang nói là "Phương pháp tĩnh nhà máy" của Joshua Bloch nhưng bạn sử dụng thuật ngữ "Mô hình phương thức nhà máy" của GoF. Hãy chỉnh sửa nó để người khác không hiểu lầm.
emeraldhieu

1
Lưu ý rằng hàm tạo không phải là riêng tư. Một lớp có thể cung cấp cả phương thức và nhà xây dựng tĩnh công cộng.
Kevin

171

GHI CHÚ! "Các phương thức tĩnhKHÔNG giống như các phương pháp Factory mô hình" (c) Effective Java, Joshua Bloch.

Phương thức Factory: "Xác định giao diện để tạo đối tượng, nhưng để các lớp thực hiện giao diện quyết định lớp nào sẽ khởi tạo. Phương thức Factory cho phép một lớp trì hoãn khởi tạo lớp cho các lớp con" (c) GoF.

"Phương thức tĩnh nhà máy chỉ đơn giản là một phương thức tĩnh trả về một thể hiện của một lớp." (c) Java hiệu quả, Joshua Bloch. Thông thường phương thức này là bên trong một lớp cụ thể.

Sự khác biệt:

Ý tưởng chính của phương thức tĩnh nhà máy là giành quyền kiểm soát đối với việc tạo đối tượng và ủy thác nó từ phương thức khởi tạo cho phương thức tĩnh. Quyết định của đối tượng được tạo giống như trong Tóm tắt Factory được thực hiện bên ngoài phương thức (trong trường hợp phổ biến, nhưng không phải luôn luôn). Trong khi ý tưởng chính (!) Của Phương thức Factory là ủy thác quyết định về trường hợp nào của lớp sẽ tạo bên trong Phương thức Factory. Ví dụ, triển khai Singleton cổ điển là trường hợp đặc biệt của phương pháp tĩnh nhà máy. Ví dụ về các phương pháp tĩnh nhà máy thường được sử dụng:

  • giá trị của
  • nhận được
  • mới

Bạn có thể cho tôi biết sự khác biệt giữa A () và A.newInstance () mới không? và bên trong A.newInstance chúng ta nên làm gì?
Thần

69

Khả năng đọc có thể được cải thiện bằng các phương pháp tĩnh nhà máy:

Đối chiếu

public class Foo{
  public Foo(boolean withBar){
    //...
  }
}

//...

// What exactly does this mean?
Foo foo = new Foo(true);
// You have to lookup the documentation to be sure.
// Even if you remember that the boolean has something to do with a Bar
// you might not remember whether it specified withBar or withoutBar.

đến

public class Foo{
  public static Foo createWithBar(){
    //...
  }

  public static Foo createWithoutBar(){
    //...
  }
}

// ...

// This is much easier to read!
Foo foo = Foo.createWithBar();

Vì vậy, tôi đã cố gắng thực hiện ví dụ của bạn nhưng tôi không chắc cách này hoạt động. Hai phương thức createdWithBar và createdWithoutBar có nghĩa vụ gọi 2 hàm tạo riêng trong lớp Foo không?
Essej

@Baxtex: Vâng. Mỗi người sẽ gọi một nhà xây dựng riêng. Có lẽ cũng giống như vậy: private Foo(boolean withBar){/*..*/} public static Foo createWithBar(){return new Foo(true);} public static Foo createWithoutBar(){return new Foo(false);}
Rasmus Faber

Tôi nghĩ rằng đây không phải là "quy mô" rất tốt. Nếu bạn có ba tham số trở lên, làm thế nào bạn có thể sử dụng ý tưởng này và tạo một tên đẹp cho phương thức?
Dherik

@Dherik: Sau đó, có lẽ bạn nên sử dụng mẫu trình xây dựng thay thế: new FooBuilder (). WithBar (). WithoutFoo (). WithBaz (). Build ();
Rasmus Faber

21
  • có tên, không giống như constructor, có thể làm rõ mã.
  • không cần tạo một đối tượng mới theo mỗi lần gọi - các đối tượng có thể được lưu trữ và sử dụng lại, nếu cần.
  • có thể trả về một kiểu con của kiểu trả về của chúng - đặc biệt, có thể trả về một đối tượng mà lớp thực hiện không xác định đối với người gọi. Đây là một tính năng rất có giá trị và được sử dụng rộng rãi trong nhiều khung công tác sử dụng các giao diện làm kiểu trả về của các phương thức tĩnh của nhà máy.

từ http://www.javapractices.com/topic/TopicAction.do?Id=21


18

Tất cả sôi sục để duy trì. Cách tốt nhất để đặt nó là bất cứ khi nào bạn sử dụngnew từ khóa để tạo một đối tượng, bạn sẽ ghép mã mà bạn đang viết cho một triển khai.

Mẫu nhà máy cho phép bạn tách biệt cách bạn tạo một đối tượng khỏi những gì bạn làm với đối tượng. Khi bạn tạo tất cả các đối tượng của mình bằng cách sử dụng các hàm tạo, về cơ bản, bạn khó kết nối mã sử dụng đối tượng để thực hiện. Mã sử ​​dụng đối tượng của bạn là "phụ thuộc" vào đối tượng đó. Điều này có vẻ không phải là một vấn đề lớn trên bề mặt, nhưng khi đối tượng thay đổi (nghĩ đến việc thay đổi chữ ký của nhà xây dựng, hoặc phân lớp đối tượng), bạn phải quay lại và sắp xếp lại mọi thứ ở mọi nơi.

Ngày nay, các nhà máy phần lớn đã bị gạt sang một bên ủng hộ việc sử dụng Dependency Injection vì họ yêu cầu rất nhiều mã nồi hơi, hóa ra hơi khó để tự duy trì. Dependency Injection về cơ bản tương đương với các nhà máy nhưng cho phép bạn chỉ định cách các đối tượng của bạn được nối với nhau theo cách khai báo (thông qua cấu hình hoặc chú thích).


3
Bạn đang nói rằng các nhà máy cần một gói cứu trợ? ;)
John Farrell

4
Haha! Trong thời đại ngày nay, tôi nghĩ tất cả chúng ta đều có thể sử dụng gói cứu trợ ... :)
cwash

11

Nếu hàm tạo của một lớp là riêng tư thì bạn không thể tạo một đối tượng cho lớp từ bên ngoài nó.

class Test{
 int x, y;
 private Test(){
  .......
  .......
  }
}

Chúng ta không thể tạo một đối tượng cho lớp trên từ bên ngoài nó. Vì vậy, bạn không thể truy cập x, y từ bên ngoài lớp. Vậy thì việc sử dụng lớp học này là gì?
Dưới đây là câu trả lời: phương pháp NHÀ MÁY .
Thêm phương thức dưới đây trong lớp trên

public static Test getObject(){
  return new Test();
}

Vì vậy, bây giờ bạn có thể tạo một đối tượng cho lớp này từ bên ngoài nó. Thích hướng này...

Test t = Test.getObject();

Do đó, một phương thức tĩnh trả về đối tượng của lớp bằng cách thực thi hàm tạo riêng của nó được gọi là phương thức FACTORY
.


1
Tại sao bạn gọi nó là một "giải pháp"? Tuyên bố một nhà xây dựng tư nhân không phải là một "vấn đề", Đó là một mẫu thiết kế.
Ojonugwa Jude Ochalifu

1
Cập nhật. Dù sao cũng cảm ơn
Santhosh

Xin chào @Santhosh Tôi có một lo ngại là Tại sao bạn không để công cụ xây dựng riêng tư công khai? Nếu bạn không muốn tạo lớp con, điều đó tốt cho tôi, nhưng nếu tôi không có ý định tạo nhà xây dựng riêng thì chúng ta có lợi ích gì đối Static Factory Methodvới nhà xây dựng công cộng không?
Thần

9

Tôi nghĩ rằng tôi sẽ thêm một số ánh sáng cho bài viết này về những gì tôi biết. Chúng tôi đã sử dụng kỹ thuật này rộng rãi trong của chúng tôi recent android project. Thay vì creating objects using new operatorbạn cũng có thể sử dụng static methodđể khởi tạo một lớp. Mã danh sách:

//instantiating a class using constructor
Vinoth vin = new Vinoth(); 

//instantiating the class using static method
Class Vinoth{
  private Vinoth(){
  }
  // factory method to instantiate the class
  public static Vinoth getInstance(){
    if(someCondition)
        return new Vinoth();
  }
}

Các phương thức tĩnh hỗ trợ tạo đối tượng có điều kiện : Mỗi lần bạn gọi hàm tạo, một đối tượng sẽ được tạo nhưng bạn có thể không muốn điều đó. giả sử bạn chỉ muốn kiểm tra một số điều kiện thì bạn muốn tạo một đối tượng mới. Bạn sẽ không tạo một phiên bản mới của Vinoth mỗi lần, trừ khi điều kiện của bạn được thỏa mãn.

Một ví dụ khác được lấy từ Java hiệu quả .

public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
}

Phương thức này chuyển một giá trị nguyên thủy boolean thành tham chiếu đối tượng Boolean. Các Boolean.valueOf(boolean)phương pháp minh họa chúng ta, nó không bao giờ tạo ra một đối tượng. Khả năng static factory methodstrả lại cùng một đối tượng từ lặp đi lặp lạiinvocations cho phép các lớp duy trì sự kiểm soát chặt chẽ đối với những trường hợp tồn tại bất cứ lúc nào.

Static factory methodslà, không giống như constructors, họ có thể trả objectvề bất kỳ subtypeloại trả lại nào của họ. Một ứng dụng của tính linh hoạt này là API có thể trả về các đối tượng mà không cần công khai các lớp của chúng. Ẩn các lớp triển khai theo cách này dẫn đến một API rất nhỏ gọn.

Calendar.getInstance () là một ví dụ tuyệt vời cho ở trên, nó tạo ra tùy thuộc vào miền địa phương một BuddhistCalendar, JapaneseImperialCalendarhoặc bởi một mặc định Georgian.

Một ví dụ khác mà tôi có thể nghĩ là Singleton pattern, nơi bạn làm cho các nhà xây dựng của mình riêng tư tạo một getInstancephương thức riêng mà bạn chắc chắn, luôn có sẵn một thể hiện.

public class Singleton{
    //initailzed during class loading
    private static final Singleton INSTANCE = new Singleton();

    //to prevent creating another instance of Singleton
    private Singleton(){}

    public static Singleton getSingleton(){
        return INSTANCE;
    }
}

4

Một phương thức nhà máy là một phương thức trừu tượng hóa việc khởi tạo một đối tượng. Nói chung các nhà máy rất hữu ích khi bạn biết rằng bạn cần một phiên bản mới của một lớp thực hiện một số giao diện nhưng bạn không biết lớp triển khai.

Điều này rất hữu ích khi làm việc với hệ thống phân cấp của các lớp liên quan, một ví dụ điển hình cho việc này sẽ là bộ công cụ GUI. Bạn có thể chỉ cần gọi mã cứng đến các nhà xây dựng để triển khai cụ thể từng tiện ích nhưng nếu bạn muốn trao đổi một bộ công cụ cho một bộ công cụ khác, bạn sẽ có rất nhiều nơi để thay đổi. Bằng cách sử dụng một nhà máy, bạn giảm số lượng mã bạn cần thay đổi.


Giả sử bạn có nhà máy của bạn trả về một loại giao diện, và không phải là lớp cụ thể mà bạn đang xử lý.
Bill Lynch

1
Câu trả lời này là về mẫu thiết kế phương thức nhà máy không phải phương thức nhà máy tĩnh. Một phương thức nhà máy tĩnh chỉ đơn giản là một phương thức tĩnh công khai trả về một thể hiện của một lớp. Xem Chương 2 của Java hiệu quả để biết thêm chi tiết.
Josh Nắng

4

Một trong những lợi thế bắt nguồn từ Nhà máy tĩnh là API có thể trả về các đối tượng mà không cần công khai các lớp của chúng. Điều này dẫn đến API rất nhỏ gọn. Trong java, điều này đạt được bởi lớp Bộ sưu tập ẩn khoảng 32 lớp khiến API bộ sưu tập rất nhỏ gọn.


2

Một phương thức nhà máy tĩnh là tốt khi bạn muốn đảm bảo rằng chỉ một trường hợp duy nhất sẽ trả về lớp cụ thể được sử dụng.

Ví dụ, trong một lớp kết nối cơ sở dữ liệu, bạn có thể chỉ muốn có một lớp tạo kết nối cơ sở dữ liệu, để nếu bạn quyết định chuyển từ Mysql sang Oracle, bạn có thể thay đổi logic trong một lớp và phần còn lại của ứng dụng sẽ sử dụng kết nối mới.

Nếu bạn muốn triển khai cơ sở dữ liệu, thì điều đó cũng sẽ được thực hiện mà không ảnh hưởng đến phần còn lại của ứng dụng.

Nó bảo vệ phần còn lại của ứng dụng khỏi những thay đổi mà bạn có thể thực hiện cho nhà máy, đó là mục đích.

Lý do khiến nó tĩnh là nếu bạn muốn theo dõi một số tài nguyên hạn chế (số lượng kết nối ổ cắm hoặc tay cầm tệp) thì lớp này có thể theo dõi số lượng đã bị bỏ qua và trả lại, vì vậy bạn không làm cạn kiệt nguồn lực hạn chế.


2

Một trong những lợi thế của các phương thức nhà máy tĩnh với hàm tạo riêng (việc tạo đối tượng phải được hạn chế cho các lớp bên ngoài để đảm bảo các thể hiện không được tạo ra bên ngoài) là bạn có thể tạo các lớp được kiểm soát cá thể . Và các lớp được kiểm soát cá thể đảm bảo rằng không tồn tại hai trường hợp riêng biệt bằng nhau ( a.equals (b) khi và chỉ khi a == b ) trong khi chương trình của bạn chạy, điều đó có nghĩa là bạn có thể kiểm tra sự bằng nhau của các đối tượng với toán tử == thay vì phương thức bằng , theo java hiệu quả.

Khả năng của các phương thức nhà máy tĩnh trả về cùng một đối tượng từ các lệnh được lặp đi lặp lại cho phép các lớp duy trì sự kiểm soát chặt chẽ đối với những trường hợp tồn tại bất cứ lúc nào. Các lớp làm điều này được cho là kiểm soát cá thể. Có một số lý do để viết các lớp kiểm soát cá thể. Kiểm soát sơ thẩm cho phép một lớp đảm bảo rằng đó là một đơn (Mục 3) hoặc không đáng kể (Mục 4). Ngoài ra, nó cho phép một lớp bất biến (Mục 15) đảm bảo rằng không tồn tại hai trường hợp bằng nhau: a.equals (b) khi và chỉ khi a == b. Nếu một lớp thực hiện đảm bảo này, thì các máy khách của nó có thể sử dụng toán tử == thay vì phương thức bằng (Object), điều này có thể dẫn đến hiệu suất được cải thiện. Các loại Enum (Mục 30) cung cấp đảm bảo này.

Từ Java hiệu quả, Joshua Bloch (Mục 1, trang 6)


1

tĩnh

Một thành viên đã khai báo với từ khóa 'tĩnh'.

phương pháp nhà máy

Các phương thức tạo và trả về các đối tượng mới.

trong Java

Ngôn ngữ lập trình có liên quan đến ý nghĩa của 'tĩnh' nhưng không liên quan đến định nghĩa của 'nhà máy'.


@Victor Phản hồi không cần chứa đối số. Sự kiện cần phải đủ: nếu gây tranh cãi, chúng có thể được hỗ trợ bằng lập luận hoặc trích dẫn. Tôi không biết có gì gây tranh cãi ở đây.
Hầu tước Lorne

Tôi đã nói rằng vì câu trả lời quá ngắn và thực sự không hiểu rõ ở cái nhìn đầu tiên, thứ hai và thứ ba, dù sao thì tùy thuộc vào OP để hỏi lại. Mặc dù vậy, tôi đã thay đổi ý định và cố gắng loại bỏ downvote, nhưng tôi không thể.
Victor

@Victor Xác định 'quá ngắn'. Đôi khi, câu trả lời thực sự chỉ là 'có', 'không', 'không' hoặc 'cả hai'. "Quá ngắn" là hoàn toàn chủ quan. Tôi vẫn không hiểu bình luận ban đầu của bạn. Bạn không cần đối số để hỗ trợ các định nghĩa. Theo định nghĩa. Tôi đã chỉnh sửa câu trả lời của mình để bây giờ có thể xóa downvote.
Hầu tước Lorne

Tất nhiên là chủ quan ... tất cả các câu trả lời stackoverflow là chủ quan, trên thực tế chúng có liên quan đến kiến ​​thức và ý chí của tác giả để trả lời. Tôi thực sự không hiểu câu trả lời của bạn, có lẽ là ngắn.
Victor

@Victor Rác. Các vấn đề thực tế không phải là chủ quan, và cũng không phải là vấn đề có thể được suy ra từ các sự kiện hoặc tiên đề. 'Quá ngắn', mặt khác là chủ quan, và tôi đã giải quyết nó. Câu trả lời này về cơ bản giống như câu trả lời này mà bạn chưa nhận xét. Nhận xét của bạn vẫn còn mơ hồ.
Hầu tước Lorne

1

Việc triển khai Java chứa các lớp tiện ích java.util.Arraysjava.util.Collections cả hai đều chứa các phương thức nhà máy tĩnh , các ví dụ về nó và cách sử dụng:

Ngoài ra lớp java.lang.String có các phương thức tĩnh như vậy :

  • String.format(...), String.valueOf(..), String.copyValueOf(...)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.