Khác biệt giữa bản sửa đổi của “Factory method”

Nội dung được xóa Nội dung được thêm vào
Đang dịch
Không có tóm lược sửa đổi
Dòng 1:
 
{{ambox
| type = content
| image = [[Image:Translation_to_vi_arrow.svg|20px|Translation to english arrow icon]]
| text = '''Bài này đang được dịch từ {{qif|test=Tiếng Anh|then=[[Tiếng Anh]]|else=ngôn ngữ khác}}.''' <br /><span style="font-size: 88%">Nếu bạn có đủ khả năng xin [{{fullurle:{{FULLPAGENAME}}|action=edit}} góp sức dịch] bài này. Nếu không tiếp tục được quan tâm, phần ngoại ngữ của bài sẽ bị xóa sau khoảng '''1 tháng'''. Xin đừng quên chuyển các mục [[Wikipedia:Thông tin kiểm chứng được|''Chú thích, Tham khảo'']] vào bài dịch để đáp ứng tiêu chuẩn. Xin tham khảo [[Trợ giúp:Sửa đổi|Hướng dẫn cách biên soạn bài]] để biết thêm chi tiết.</span>
}}
[[Thể loại:Bài đang dịch|{{PAGENAME}}]]
 
 
[[Image:FactoryMethod.svg|thumb|right|300px|Factory method in [[Unified Modeling Language|UML]]]]
[[Image:Factory Method pattern in LePUS3.png|thumb|right|300px|Factory Method in [[Lepus3|LePUS3]]]]
Hàng 20 ⟶ 11:
* "Factory method" thường được dùng trong bộ phát triển (toolkit) hay framework, ở đó, đoạn mã của framework cần thiết phải tạo một đối tượng là những lớp con của ứng dụng sử dụng framework đó.
 
==Những lợi ích khác và biến thể==
==Other benefits and variants==
Cho dù động cơ của mẫu thiết kế "Factory method" là cho phép lớp con được chọn lựa kiểu đối tượng nào sẽ được tạo, việc sử dụng factory method cũng có những lợi ích khác. Bởi thế, việc thường xuyên sử dụng "factory method" không chỉ cho việc tạo đối tượng một cách đa dạng mà còn lợi dụng những lợi ích khác. Những hàm như thế thì thường là tĩnh.
Although the motivation behind the factory method pattern is to allow subclasses to choose which type of object to create, there are other benefits to using factory methods, many of which do not depend on subclassing.
Therefore, it is common to define "factory methods" that are not polymorphic to create objects in order to gain these other benefits. Such methods are often static.
 
===EncapsulationTóm lược===
Factory method gói gọn lại việc tạo đối tượng. Điều này hữu dụng nếu quá trình tạo phức tạp. Ví dụ như nó phụ thuộc vào những điều chỉnh trong tập tin cấu hình hay phụ thuộc vào thông tin của người dùng nhập vào.
Factory methods encapsulate the creation of objects.
This can be useful if the creation process is very complex, for example if it depends on settings in configuration files or on user input.
 
Consider asdụ anmột examplechương atrình programđọc totập readtin [[imageảnh file]]s andtạo makeảnh [[thumbnail]]s outcủa of them.
Chương trình hỗ trợ nhiều định dạng ảnh khác nhau, và mỗi định dạng ảnh sẽ có một lớp hỗ trợ việc đọc tập tin.
The program supports different image formats, represented by a reader class for each format:
<source lang="java">
public interface ImageReader
Hàng 55 ⟶ 44:
}
</source>
Mỗi khi chương trình đọc một ảnh, nó cần phải tạo một đối tượng phù hợp để đọc ảnh đó dựa vào những thông tin trong tập tin. Việc này có thể gói gọn trong factory method:
Each time the program reads an image it needs to create a reader of the appropriate type based on some information in the file. This logic can be encapsulated in a factory method:
<source lang="java">
public class ImageReaderFactory
Hàng 75 ⟶ 64:
</source>
 
Đoạn mã trong ví dụ bên trên sử dụng lệnh switch để chỉ định kết hợp một <code>imageType</code> với một đối tượng factory cụ thể. Ngoài ra, có thể thay thế câu lệnh switch bằng cách sử dụng một mảng.
The code fragment in the previous example uses a [[switch statement]] to associate an <code>imageType</code> with a specific [[factory object]]. Alternatively, this association could also be implemented as a [[map (computer science)|mapping]]. This would allow the switch statement to be replaced with an [[associative array]] lookup.
 
==LimitationsGiới hạn==
Có 3 giới hạn đối với việc sử dụng factory method. Một liên quan đến việc sửa đổi (tạm dịch từ refactoring) mã nguồn hiện tại; Hai vấn đề khác liên quan đến thừa kế.
There are three limitations associated with the use of the factory method. The first relates to [[code refactoring|refactoring]] existing code; the other two relate to inheritance.
 
* Giới hạn đầu tiên là việc sửa đổi (refactoring) một lớp đã có sẵn để sử dụng factory sẽ làm hỏng ứng dụng. Ví dụ, nếu lớp Complex là một lớp chuẩn, có thể tồn tại nhiều đoạn mã sử dụng lớp này như sau:
* The first limitation is that refactoring an existing class to use factories breaks existing clients. For example, if class Complex was a standard class, it might have numerous clients with code like:
 
<source lang="java">Complex c = new Complex(-1, 0);</source>
 
:Một khi chúng ta thấy cần thiết phải có hai factory khác nhau, chúng ta thay đổi lớp này. Tuy nhiên, vì hàm khởi tạo (constructor) bây giờ trở thành ''private'', đoạn mã này sẽ không được dịch nữa.
:Once we realize that two different factories are needed, we change the class (to the code shown earlier). But since the constructor is now private, the existing client code no longer compiles.
 
* Giới hạn thứ hai là do mẫu thiết kế này dựa vào việc sử dụng hàm khởi tạo ''private'', lớp này sẽ không thể được thừa kế và mở rộng. Các lớp con phải thừa kế hàm khởi tạo của lớp cha, nhưng việc này không thực hiện được vì hàm khởi tạo là ''private''.
* The second limitation is that, since the pattern relies on using a private constructor, the class cannot be extended. Any subclass must invoke the inherited constructor, but this cannot be done if that constructor is private.
 
* Giới hạn thứ ba là, nếu chúng ta mở rộng một lớp (ví dụ: tạo một hàm khởi tạo ''protected'' -- điều này nguy hiểm nhưng chấp nhận được), lớp con phải cung cấp lại tất cả các hàm factory với tất cả thông số phải chính xác (bao gồm tên hàm và tham số). Ví dụ, nếu lớp StrangeComplex thừa kế lớp Complex, trừ khi StrangeComplex cung cấp tất cả các hàm factory, nếu không việc gọi
* The third limitation is that, if we do extend the class (e.g., by making the constructor protected -- this is risky but possible), the subclass must provide its own re-implementation of all factory methods with exactly the same signatures. For example, if class StrangeComplex extends Complex, then unless StrangeComplex provides its own version of all factory methods, the call StrangeComplex.fromPolar(1, pi) will yield an instance of ''Complex'' (the superclass) rather than the expected instance of the subclass.
* The third limitation is that, if we do extend the class (e.g., by making the constructor StrangeComplex.fromPolar(1, pi) sẽ trả ra đối tượng ''Complex'' thay vì đối tượng con (là StrangeComplex).
 
Những vấn đề trên có thể giải quyết bằng cách sử dụng ngôn ngữ lập trình (thay vì sử dụng mẫu thiết kế).
All three problems could be alleviated by altering the underlying programming language to make factories first-class class members (rather than using the design pattern).
 
==ExamplesVí dụ==
===C#===
Pizza example:
Hàng 188 ⟶ 178:
}
 
//Sử dụng
//Usage
var pizzaPrice = new PizzaFactory().createPizza("Ham and Mushroom").getPrice();
alert(pizzaPrice);
</source>
 
===Ruby=Sử dụng==
*[[ADO.NET]], [http://msdn2.microsoft.com/en-us/library/system.data.idbcommand.createparameter.aspx IDbCommand.CreateParameter] là ví dụ của việc dùng factory method để kết nối những lớp song song.
Pizza example:
*[[Qt (toolkit)|Qt]], [http://doc.trolltech.com/4.0/qmainwindow.html#createPopupMenu QMainWindow::createPopupMenu] is a factory method declared in a framework which can be overridden in application code.
<source lang="ruby">
class HamAndMushroomPizza
def price
8.50
end
end
 
class DeluxePizza
def price
10.50
end
end
 
class SeafoodPizza
def price
11.50
end
end
 
class PizzaFactory
def create_pizza(style='')
case style
when 'Ham and Mushroom'
HamAndMushroomPizza.new
when 'DeluxePizza'
DeluxePizza.new
when 'Seafood Pizza'
SeafoodPizza.new
else
DeluxePizza.new
end
end
end
 
# usage
factory = PizzaFactory.new
pizza = factory.create_pizza('Ham and Mushroom')
pizza.price #=> 8.5
# bonus formatting
formatted_price = sprintf("$%.2f", pizza.price) #=> "$8.50"
# one liner
sprintf("$%.2f", PizzaFactory.new.create_pizza('Ham and Mushroom').price) #=> "$8.50"
</source>
 
 
===Python===
<source lang="python">
# Our Pizzas
 
class Pizza:
HAM_MUSHROOM_PIZZA_TYPE = 0
DELUXE_PIZZA_TYPE = 1
SEAFOOD_PIZZA_TYPE= 2
 
def __init__(self):
self.__price = None
 
def getPrice(self):
return self.__price
 
class HamAndMushroomPizza(Pizza):
def __init__(self):
self.__price = 8.50
 
class DeluxePizza(Pizza):
def __init__(self):
self.__price = 10.50
 
class SeafoodPizza(Pizza):
def __init__(self):
self.__price = 11.50
 
class PizzaFactory:
def createPizza(self, pizzaType):
if pizzaType == Pizza.HAM_MUSHROOM_PIZZA_TYPE:
return HamAndMushroomPizza()
elif pizzaType == Pizza.DELUXE_PIZZA_TYPE:
return DeluxePizza()
elif pizzaype == Pizza.SEAFOOD_PIZZA_TYPE:
return SeafoodPizza()
else:
return DeluxePizza()
 
# Usage
pizzaPrice = PizzaFactory().createPizza(Pizza.HAM_MUSHROOM_PIZZA_TYPE).getPrice()
print "$%.02f" % pizzaPrice
</source>
 
==Uses==
*In [[ADO.NET]], [http://msdn2.microsoft.com/en-us/library/system.data.idbcommand.createparameter.aspx IDbCommand.CreateParameter] is an example of the use of factory method to connect parallel class hierarchies.
*In [[Qt (toolkit)|Qt]], [http://doc.trolltech.com/4.0/qmainwindow.html#createPopupMenu QMainWindow::createPopupMenu] is a factory method declared in a framework which can be overridden in application code.
* In [[Java (programming language)]] several factories are used in the [http://java.sun.com/j2se/1.4.2/docs/api/javax/xml/parsers/package-summary.html javax.xml.parsers] package. e.g. javax.xml.parsers.DocumentBuilderFactory or javax.xml.parsers.SAXParserFactory.
 
==SeeXem alsothêm==
*[[Design Patterns]], the highly-influential book
*[[Abstract factory pattern|Abstract Factory]], a pattern often implemented using factory methods
Hàng 295 ⟶ 195:
*[[Factory object]]
 
==ReferencesTham khảo==
*{{cite book
| last = Fowler | first = Martin
Hàng 324 ⟶ 224:
}}
 
==Các tham khảo khác==
==External links==
*[http://www.lepus.org.uk/ref/companion/FactoryMethod.xml Factory method in UML and in LePUS3] (a Design Description Language)
*[http://c2.com/cgi/wiki?FactoryMethodPattern Description from the Portland Pattern Repository]