工厂模式:支持新的具体类型
Factory Pattern: Supporting new concrete types
我正在研究 this link 中的 Factory Pattern
。
在写完一个普通的工厂之后,作者继续设计一个工厂,我们不必修改工厂的代码来添加新的具体实现。 (假设有一个 Product
接口,工厂提供它的实现)。
为了实现这一点,作者说:
We add a new abstract method in the product abstract class. Each concrete class will implement this method to create a new object of the same type as itself.
此代码段如下:
abstract class Product
{
public abstract Product createProduct();
...
}
class OneProduct extends Product
{
...
static
{
ProductFactory.instance().registerProduct("ID1", new OneProduct());
}
public OneProduct createProduct()
{
return new OneProduct();
}
...
}
class ProductFactory
{
public void registerProduct(String productID, Product p) {
m_RegisteredProducts.put(productID, p);
}
public Product createProduct(String productID){
((Product)m_RegisteredProducts.get(productID)).createProduct();
}
}
我在这里有疑问。我们已经将 OneProduct 的 实例 注册到工厂。然后在运行时,我们调用 createProduct()
方法再次创建 Oneproduct
的新实例。
这是正确的做法吗?我们必须在这里创建 两个 OneProduct
的实例,我认为这是错误的。
之所以需要两个实例,是因为调用createProduct()
方法时使用了多态性。也就是说,每个具体产品都有自己的createProduct()
实现,你可以用同样的方法创建所有的产品,因为它们都继承自同一个抽象class.
但要做到这一点,您需要有实例。您不能对静态方法使用多态性。您只能覆盖实例方法。因此你需要一个实例,来创建一个实例。
但是,实例不必与其创建的类型相同。它只需要是实现所需方法的 class 的实例。在 Java 8 中,您可能会使用 Supplier<Product>
.
获得更清晰的解决方案
abstract class Product
{
...
}
class OneProduct extends Product
{
...
static
{
ProductFactory.instance().registerProduct("ID1", OneProduct::new);
}
...
}
class ProductFactory
{
Map<String,Supplier<Product>> m_RegisteredProducts = new HashMap<>();
public void registerProduct(String productID, Supplier<Product> p) {
m_RegisteredProducts.put(productID, p);
}
public Product createProduct(String productID){
// There should be a null check here...
return m_RegisteredProducts.get(productID).get();
}
}
实质上,方法引用为您提供了一个实现 Supplier<Product>
的小对象,您可以在其上调用 get()
,这将使用默认构造函数创建一个新产品。
您提到的文章很旧。我相信它早于 Java 1.2,因为它仍然使用 Hashtable
而不是现代地图,并且没有泛型。原则保持不变,但有更现代的方法来实现它们。
我正在研究 this link 中的 Factory Pattern
。
在写完一个普通的工厂之后,作者继续设计一个工厂,我们不必修改工厂的代码来添加新的具体实现。 (假设有一个 Product
接口,工厂提供它的实现)。
为了实现这一点,作者说:
We add a new abstract method in the product abstract class. Each concrete class will implement this method to create a new object of the same type as itself.
此代码段如下:
abstract class Product
{
public abstract Product createProduct();
...
}
class OneProduct extends Product
{
...
static
{
ProductFactory.instance().registerProduct("ID1", new OneProduct());
}
public OneProduct createProduct()
{
return new OneProduct();
}
...
}
class ProductFactory
{
public void registerProduct(String productID, Product p) {
m_RegisteredProducts.put(productID, p);
}
public Product createProduct(String productID){
((Product)m_RegisteredProducts.get(productID)).createProduct();
}
}
我在这里有疑问。我们已经将 OneProduct 的 实例 注册到工厂。然后在运行时,我们调用 createProduct()
方法再次创建 Oneproduct
的新实例。
这是正确的做法吗?我们必须在这里创建 两个 OneProduct
的实例,我认为这是错误的。
之所以需要两个实例,是因为调用createProduct()
方法时使用了多态性。也就是说,每个具体产品都有自己的createProduct()
实现,你可以用同样的方法创建所有的产品,因为它们都继承自同一个抽象class.
但要做到这一点,您需要有实例。您不能对静态方法使用多态性。您只能覆盖实例方法。因此你需要一个实例,来创建一个实例。
但是,实例不必与其创建的类型相同。它只需要是实现所需方法的 class 的实例。在 Java 8 中,您可能会使用 Supplier<Product>
.
abstract class Product
{
...
}
class OneProduct extends Product
{
...
static
{
ProductFactory.instance().registerProduct("ID1", OneProduct::new);
}
...
}
class ProductFactory
{
Map<String,Supplier<Product>> m_RegisteredProducts = new HashMap<>();
public void registerProduct(String productID, Supplier<Product> p) {
m_RegisteredProducts.put(productID, p);
}
public Product createProduct(String productID){
// There should be a null check here...
return m_RegisteredProducts.get(productID).get();
}
}
实质上,方法引用为您提供了一个实现 Supplier<Product>
的小对象,您可以在其上调用 get()
,这将使用默认构造函数创建一个新产品。
您提到的文章很旧。我相信它早于 Java 1.2,因为它仍然使用 Hashtable
而不是现代地图,并且没有泛型。原则保持不变,但有更现代的方法来实现它们。