目录
简单工厂模式
在讲解工厂方法模式之前,我们先来看一下简单工厂模式。
1、概述
定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
当我们需要创建各种不同对象,这些类称为具体产品类(ConcreteProduct),而将它们公共的代码进行抽象和提取后封装在一个抽象产品类或产品接口(Product)中,每一个具体产品类都是抽象产品类的子类;然后提供一个工厂类(Factory)用于创建各种产品,在工厂类中提供一个创建产品的工厂方法,该方法可以根据所传入的参数不同创建不同的具体产品对象;客户端只需调用工厂类的工厂方法并传入相应的参数即可得到一个产品对象。而无须直接使用new关键字来创建对象,也就是对象的创建由工厂来帮你完成、你不需要知道他的创建过程。
2、适用场景
(1) 工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
(2) 客户端只知道传入工厂类的参数,对于如何创建对象并不关心。
3、UML类图分析
我们以产品工厂生产产品为例:
4、参与者
(1)ProductFactory (工厂角色):
工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象。
(2)Product (抽象产品类或接口):
它是工厂类所创建的所有对象的父类,所创建的具体产品对象都是其子类对象。
(3)ConcreteProduct (具体产品角色):
它是简单工厂模式的创建目标。
5、用例学习
(1)产品接口类:Product.java
/**
* 产品接口
*/
public interface Product {
/**
* 生产方法
*/
void produce();
}
(2) 具体的产品类A:ConcreteProductA.java
/**
* 具体的产品A
*/
public class ConcreteProductA implements Product{
@Override
public void produce() {
System.out.println("产品A生产了...");
}
}
(3) 具体的产品类A:ConcreteProductB.java
/**
* 具体的产品B
*/
public class ConcreteProductB implements Product{
@Override
public void produce() {
System.out.println("产品B生产了...");
}
}
(4) 具体的产品类A:ConcreteProductC.java
/**
* 具体的产品C
*/
public class ConcreteProductC implements Product{
@Override
public void produce() {
System.out.println("产品C生产了...");
}
}
(5)生产产品的工厂类 (简单的工厂类/静态工厂类):ProductFactory.java
/**
* 生产产品的工厂类(简单工厂类/静态工厂类)
*/
public class ProductFactory {
/**
* 生产产品的静态工厂方法
* @param productType 产品类型
* @return Product
*/
public static Product createProduct(String productType) {
Product product = null;
if ("A".equals(productType)) {
product = new ConcreteProductA();
} else if ("B".equals(productType)) {
product = new ConcreteProductB();
} else if ("C".equals(productType)) {
product = new ConcreteProductC();
}
return product;
}
}
(6) 测试类:ProductTest.java
public class ProductTest {
public static void main(String[] args) {
//生产产品A
Product productA = ProductFactory.createProduct("A");
productA.produce();
//生产产品B
Product productB = ProductFactory.createProduct("B");
productB.produce();
//生产产品C
Product productC = ProductFactory.createProduct("C");
productC.produce();
}
}
(7)运行效果如下:
产品A生产了...
产品B生产了...
产品C生产了...
以上就是简单工厂模式的简单实现,试想一下,如果我们现在需要新增加一个产品类,那是不是要去修改我们的工厂类的方法,需要增加一个if条件的判断。
所以,它是对修改开放的,很显然,违背了我们的设计原则里的开闭原则。
那么,怎么解决这个问题呢,下面就来看工厂方法模式。
工厂方法模式
1、UML类图
我们还是用产品工厂生产产品的例子:
2、参与者
(1)ProductFactory (抽象工厂角色):
工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象。
(2)ProductxFactory (具体工厂角色):
每个具体工厂的角色,只能生产特定类型的产品。
(3)Product (抽象产品类或接口):
它是工厂类所创建的所有对象的父类,所创建的具体产品对象都是其子类对象。
(4)ConcreteProduct (具体产品角色):
它是简单工厂模式的创建目标。
3、用例学习
在以上简单工厂的基础上,我们进行改造和补充。
(1)修改ProductFactory类为接口
/**
* 生产产品的工厂接口
*/
public interface ProductFactory {
/**
* 生产产品的工厂方法
* @return Product
*/
Product createProduct();
}
(2)增加具体产品工厂类:ProductAFactory.java
/**
* 具体的产品工厂A
*/
public class ProductAFactory implements ProductFactory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
(3)增加具体产品工厂类:ProductBFactory.java
/**
* 具体的产品工厂B
*/
public class ProductBFactory implements ProductFactory {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
(4)增加具体产品工厂类:ProductCFactory.java
/**
* 具体的产品工厂C
*/
public class ProductCFactory implements ProductFactory {
@Override
public Product createProduct() {
return new ConcreteProductC();
}
}
(5)测试类:ProductTest.java
public class ProductTest {
public static void main(String[] args) {
//生产产品A
ProductFactory productFactoryA = new ProductAFactory();
Product productA = productFactoryA.createProduct();
productA.produce();
//生产产品B
ProductFactory productFactoryB = new ProductBFactory();
Product productB = productFactoryB.createProduct();
productB.produce();
//生产产品C
ProductFactory productFactoryC = new ProductCFactory();
Product productC = productFactoryC.createProduct();
productC.produce();
}
}
(6)测试结果,和简单工厂模式一样
产品A生产了...
产品B生产了...
产品C生产了...
4、优缺点
优点:
符合开闭原则,对修改关闭,对扩展开放。
缺点:
如果我们需要增加新的产品类,我们需要创建对应的具体的产品工厂类,这样类的数量会越来越多,不易维护。
总结
其实工厂方法的本质是,将简单工厂的内部逻辑判断转移到了客户端(调用方)这里,也就是如果我们想要增加功能,就需要去修改客户端(调用方)的代码。
所以,工厂方法模式还是违背了开闭原则里的对修改关闭。
那么,有没有什么办法可以解决这个问题呢?
答案是有的,那就是抽象工厂模式,这个我们后面的文章会进行讲解,这里就不展开了。
抽象工厂模式,敬请期待......
参考资料:
《大话设计模式》