工厂方法模式
认识
- 工厂方法的主要功能是让父类在不知道具体实现的情况下,完成自身的功能调用,而具体的实现延迟到子类来实现.
- 工厂方法模式通常是针对Product接口的每个实现类都提供一个与之对应的Factory实现类用于创建该对象,这样能够实现更好的扩展性。
- 也可以把父类实现为一个具体的类,同时在父类中提供获取所需对象的默认实现方法,这样就算没有具体的子类去创建对象,也能够完成功能运行。
思考
- 工厂方法的本质:工厂是抽象的,只定义需要的对象,所需对象的创建延迟到工厂的子类中实现
- 相比于简单工厂和抽象工厂,有更好的扩展性,当增加一个Product的实现类时,只需要添加一个Factory与之对应的实现类就行。
- 工厂方法模式中工厂实现类一次方法只操作一个接口返回值,抽象工厂模式操作的是多个接口
优缺点
- 可以在不知道具体实现的情况下编程,解耦合。
- 更容易扩展对象的新版本,当有一个新的对象需要创建的时候创建一个新的工厂实现类返回新的对象。
- 缺点是每个Product的实现都需要创建一个Factory的实现,增加了客户端调用的选择难度。
使用场景
- 工厂方法模式作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式,比静态工厂模式更好的扩展。
- 工厂方法模式将具体的操作延迟到子类实现,当父类不做任何操作,将具体操作通过抽象方法延迟到子类去实现的时候可以使用。
- 当父类的操作需要一个对象的时候,提供抽象方法,让子类实现抽象方法创建需要的对象,同时在父类中定义使用该对象的公共方法,实现依赖倒置。
UML图
封装Product实现类的具体细节,创建一个抽象工厂,为每个Product接口的实现类都创建一个工厂实现类,在抽象方法中创建对应的Product的实现类对象。之后如果扩展Product的实现类,只需要扩展一个对象的工厂实现类就行。
客户端操作工厂方法的过程
代码实现
/**
* 产品接口
*/
public interface IProduct {
public void operation();
}
/**
* 产品实现类A
*/
public class ConcreateProductA implements IProduct {
public void operation() {
System.out.println("创建产品A");
}
}
/**
* 产品实现类B
*/
public class ConcreateProductB implements IProduct {
public void operation() {
System.out.println("创建产品B");
}
}
/**
* 抽象工厂类
*
*/
public abstract class Factory {
/**
* 定义抽象,具体实现延迟到子类中实现
*/
protected abstract IProduct getProduct();
/**
* 提供方法供客户端调用
*/
public IProduct createProduct() {
// 进行操作
IProduct product = this.getProduct();
// 进行操作
return product;
}
}
/**
* 工厂实现类A
*/
public class ConcreateFacotryA extends Factory {
/**
* 实现类中创建对应的product的子类返回
*/
@Override
protected IProduct getProduct() {
return new ConcreateProductA();
}
}
/**
* 工厂实现类B
*/
public class ConcreateFacotryB extends Factory {
/**
* 实现类中创建对应的product的子类返回
*/
@Override
protected IProduct getProduct() {
return new ConcreateProductB();
}
}
/**
* 客户端调用
*/
public class Client {
public static void main(String[] args) {
// 客户端调用 Factory的 ConcreateFacotryA 实现类创建对象
Factory factoryA = new ConcreateFacotryA();
IProduct productA = factoryA.createProduct();
productA.operation();
// 客户端调用 Factory的 ConcreateFacotryB 实现类创建对象
Factory factoryB = new ConcreateFacotryB();
IProduct productB = factoryB.createProduct();
productB.operation();
}
}
通过工厂方法模式实现依赖倒置,父类(接口)无法new实例,只定义操作,而操作中所需要的外部对象,由子类实现抽象方法去创建,将对象的创建延迟到子类中,能够实现更好的扩展。同时实现依赖倒置和延迟加载。
public abstract class A1 {
/**
* 工厂方法,创建C1,类似于从子类注入进来的途径
* @return C1的对象实例
*/
protected abstract C1 createC1();
public void t1(){
//这里需要使用C1,可是不知道究竟是用哪一个,也就不主动去创建C1了,怎么办?
//反正会在子类里面实现,这样更省心,这里不用管怎么获取C1,直接使用就好了
createC1().tc();
}
}
public class A {
/**
* 等待被注入进来
*/
private C c = null;
/**
* 注入资源C的方法
* @param c 被注入的资源
*/
public void setC(C c){
this.c = c;
}
public void t1(){
//这里需要使用C类,可是又不让主动去创建C了,怎么办?
//反正就要求从外部注入,这样更省心,
//自己不用管怎么获取C,直接使用就好了
c.tc();
}
}
public class A2 extends A1 {
protected C1 createC1() {
//真正的选择具体实现,并创建对象
return new C2();
}
}