1、概念简介
工厂方法(FactoryMethod)模式是类的创建模式,其用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”
在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不接触哪一个产品类被实例化这种细节。这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。
2、角色结构
-
抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
-
具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
-
抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
-
具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
3、UML类图
4、代码实现
举例:学雷锋
1.抽象产品类
LeiFeng
package com.bing.factory_method05;
//雷锋,具体的类抽象
public class LeiFeng {
public void Sweep(){
System.out.println("扫地");
}
public void Wash(){
System.out.println("洗衣服");
}
public void BuyRice(){
System.out.println("买米");
}
}
2.具体产品类
Undergraduate
package com.bing.factory_method05;
//学雷锋的学生,具体的类
public class Undergraduate extends LeiFeng{
}
Volunteer
package com.bing.factory_method05;
//学雷锋的志愿者,具体的类
public class Volunteer extends LeiFeng{
}
3.抽象工厂类
IFactory
package com.bing.factory_method05;
//工厂接口
public interface IFactory {
LeiFeng CreateLeiFeng();
}
4.具体工厂类
UndergraduateFactory
package com.bing.factory_method05;
//具体的学雷锋的学生工厂
public class UndergraduateFactory implements IFactory{
@Override
public LeiFeng CreateLeiFeng() {
return new Undergraduate();
}
}
VolunteerFactory
package com.bing.factory_method05;
//具体的学雷锋志愿者的工厂
public class VolunteerFactory implements IFactory{
@Override
public LeiFeng CreateLeiFeng() {
return new Volunteer();
}
}
5、测试代码
package com.bing.factory_method05;
public class Test {
public static void main(String[] args) {
UndergraduateFactory factory = new UndergraduateFactory(); //这里只需要改成所需要调用的对象即可
LeiFeng student = factory.CreateLeiFeng();
student.BuyRice();
student.Wash();
student.Sweep();
}
}
5、工厂方法模式优缺点
优点
-
工厂方法模式是完全符合开闭原则的;
-
工厂模式是一种典型的解耦模式,可以降低对象之间的耦合度;
-
工厂模式是依靠抽象架构的,它把实例化产品的任务交由实现类完成,扩展性比较好。
-
可以使代码结构清晰,有效地封装变化。
-
对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
缺点
- 简单的对象应用时,不适合工厂方法模式。
模式应用
工厂方法经常用在以下两种情况中:
-
第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。Java Collection中的iterator() 方法即属于这种情况。
-
第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。