一.什么是工厂方法模式?
工厂方法模式是一种创建型类模式。
工厂方法模式的意图是定义一个创建对象的接口,让子类决定实例化哪一个类。这种模式通过将对象的创建逻辑分散到各个具体的工厂类中,而不是集中在一个工厂类中,从而实现更灵活和易于扩展的系统结构。它的核心结构有四个角色,分别是抽象工厂;具体工厂;抽象产品;具体产品。工厂方法模式的核心思想是将创建对象的责任委托给子类,而不是在父类中直接实例化对象。父类定义一个创建对象的接口,而子类负责实现这个接口,从而决定创建哪种类型的对象。这种模式进一步抽象化的好处是,使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品,从而解决了许多简单工厂模式的问题。
二.类图
三.实例
例子1:
创建一个工厂,专门生产学生卡。用工厂方法模式实现,可以将抽象的工厂和产品放在一个包里,具体的产品工厂和产品放在另一个包里。
Factory.java
package Framework;
public abstract class Factory {
public final Product create(String owner) {
Product p=createProduct(owner);
registerProduct(p);
return p;
}
protected abstract Product createProduct(String owner);
protected abstract void registerProduct(Product product);
}
IDcardFactory.java
package IDcard;
import Framework.*;
import java.util.*;
public class IDcardFactory extends Factory{
private List owners= new ArrayList();
@Override
protected Product createProduct(String owner) {
// TODO Auto-generated method stub
return new IDcard(owner);
}
@Override
protected void registerProduct(Product product) {
// TODO Auto-generated method stub
owners.add(((IDcard)product).getOwner());
}
public List getOwners() {
return owners;
}
}
IDcard.java
package IDcard;
import Framework.*;
public class IDcard extends Product{
private String owner;
public IDcard(String owner){
System.out.println("制作"+owner+"的ID卡");
this.owner=owner;
}
public String getOwner() {
return owner;
}
@Override
public void use() {
// TODO Auto-generated method stub
System.out.println("使用"+owner+"的ID卡");
}
}
Product.java
package Framework;
public abstract class Product {
public abstract void use();
}
Main.java
import Framework.*;
import IDcard.*;
public class Main {
public static void main(String []args) {
Factory factory=new IDcardFactory();
Product card1=factory.create("小明");
Product card2=factory.create("小美");
Product card3=factory.create("小强");
card1.use();
card2.use();
card3.use();
}
}
运行结果:
例子二.
在上面的基础上增加一个生产教材的工厂。
textbook.java
package Textbook;
import Framework.*;
public class Textbook extends Product{
private String name;
public String getName() {
return name;
}
@Override
public void use() {
// TODO Auto-generated method stub
System.out.println("使用教材"+name);
}
public Textbook(String name){
this.name=name;
System.out.println("生产教材"+name);
}
}
textbookFactory.java
package Textbook;
import Framework.*;
import java.util.*;
public class TextbookFactory extends Factory{
private List textbooks=new ArrayList();
@Override
protected Product createProduct(String name) {
// TODO Auto-generated method stub
return new Textbook(name);
}
@Override
protected void registerProduct(Product product) {
// TODO Auto-generated method stub
textbooks.add(((Textbook)product).getName());
}
public List getTextbooks() {
return textbooks;
}
}
Main.java
import Framework.*;
import IDcard.*;
public class Main {
public static void main(String []args) {
Factory factory=new TextbookFactory();
Product textbook1=factory.create("软件工程");
Product textbook2=factory.create("网络基础");
Product textbook3=factory.create("Linux");
textbook1.use();
textbook2.use();
textbook3.use();
}
}
运行结果:
四.习题
习题4-1参考答案:
如果IDcard的构造函数是用public修饰的,会导致不使用Factory,在IDcard所在包外直接IDcard idcard=new IDcard()来创建IDcard对象。这样就不符合工厂方法了。
习题4-2参考答案:
1)我的答案
在IDcard.java中添加属性number,只修改IDcard包中的两个类,Framwork包中保持不变。Main类保持不变。
IDcard.java
package IDcard;
import Framework.*;
public class IDcard extends Product{
private String owner;
private long number;
public IDcard(String owner,long number){
System.out.println("制作"+owner+"的ID卡");
this.owner=owner;
this.number=number;
}
public String getOwner() {
return owner;
}
@Override
public void use() {
// TODO Auto-generated method stub
System.out.println("使用"+owner+"的ID卡,"+"卡号为"+number);
}
}
IDcardFactory.java
package IDcard;
import Framework.*;
import java.util.*;
public class IDcardFactory extends Factory{
private List owners= new ArrayList();
private long number=202200;
@Override
protected void registerProduct(Product product) {
// TODO Auto-generated method stub
owners.add(((IDcard)product).getOwner());
}
public List getOwners() {
return owners;
}
@Override
protected Product createProduct(String name) {
// TODO Auto-generated method stub
return new IDcard(name,number++);
}
}
运行结果:
2)参考答案
将IDcrad的createProduct方法设置为synchronized进程同步控制方法。好处:避免在多线程调用情况下出现同一个number.
protected synchronized Product createProduct(String name) {
// TODO Auto-generated method stub
return new IDcard(name,number++);
}
习题4-3参考答案:
public abstract product(){}错误,因为,不能定义抽象构造方法,用abstract 修饰是可以被实现的,这样才有意义,而构造方法不能被实现。