title: Factory Method模式
tag: 笔记 设计模式
![image-20231020144212465](https://i-blog.csdnimg.cn/blog_migrate/f53c6aaee24a29ee81d25475a97c3c1d.png)
Factory Method模式
在Template Method
模式中,我们在父类中规定处理的流程,在子类中实现具体的处理。如果我们将该模式用于生成实例,它就演变为本章中我们所要学习的Factory Method
模式。
Factory
有“工厂”的意思。用Template Method
模式来构建生成实例的工厂,这就是FactoryMethod
模式。
在Factory Method
模式中,父类决定实例的生成方式,但并不决定所要生成的具体的类,具体的处理全部交给子类负责。这样就可以将生成实例的框架(framework
)和实际负责生成实例的类解耦。
示例程序
该示例程序的作用是制作身份证(IDCart),它含有两个不同包和4个类:
framework
包:组成生成实例的框架。Factory
类:制作实例的抽象类。Product
类:被制作实例的抽象类。
IDCard
包:负责实际加工和生成实例。IDCartFactory
:继承Factory
抽象类,实际生产实例和加工的类。IDCart
:继承Product
类,实际被生产的类。
UML类图:
![image-20231020150031253](https://i-blog.csdnimg.cn/blog_migrate/b8ed33229cbb40ad1a975932c43fc0d4.png)
Product抽象类
public abstract class Product {
public abstract void use();
}
该类用于表示“产品”,类中只声明了user
一个抽象方法,表示了这个产品是任意可以use
的东西。
Factory抽象类
public abstract class Factory {
public abstract Product createProduct(String owner);
public abstract void RegisterProduct(Product product);
public Product create(String owner){
Product product = createProduct(owner);
RegisterProduct(product);
return product;
}
}
这里我们使用了Template Method
模式。我们声明了createProduct
和RegisterProduct
,将生成和注册实例具体处理交由子类处理,而在Create
方法(模板方法)中调用了两个抽象方法。
IDCart类
以上便是框架(framework)的代码。下面就是具体实现功能的类了。
public class IDCart extends Product {
private String owner;
private int serial;
IDCart(String owner,int serial){
this.owner = owner;
this.serial = serial;
System.out.println(owner + "的IDCart制作好了!编号为:" + serial);
}
@Override
public void use() {
System.out.println(owner + "的IDCart被使用了!编号为:" + serial);
}
public String getOwner() {
return owner;
}
public int getSerial() {
return serial;
}
}
继承了Product
类,并且IDCart
具有两个属性owner
和serial
。并且该类的构造方法的访问修饰是缺省的,防止本包外的地方访问该方法生成实例。
IDCartFactory类
public class IDCartFactory extends Factory {
private Map<String,Integer> database = new HashMap<>();//存储IDCart的主人和编号
private int serial = 1;//编号
@Override
public Product createProduct(String owner) {
return new IDCart(owner,serial++);
}
@Override
public void RegisterProduct(Product product) {
IDCart idCart = (IDCart) product;
database.put(idCart.getOwner(),idCart.getSerial());
}
public Map getOwners() {
return database;
}
}
该类继承了Factory
抽象类,负责生成IDCart
实例和加工。
测试
public static void main(String[] args) {
Factory factory = new IDCartFactory();
Product owner1 = factory.create("小红");
Product owner2 = factory.create("小明");
Product owner3 = factory.create("小刚");
owner1.use();
owner2.use();
owner3.use();
}
我们先生成三张IDCart,并使用。
输出:
小红的IDCart制作好了!编号为:1
小明的IDCart制作好了!编号为:2
小刚的IDCart制作好了!编号为:3
小红的IDCart被使用了!编号为:1
小明的IDCart被使用了!编号为:2
小刚的IDCart被使用了!编号为:3
Factory Mothod模式中的角色
Product
(产品)
Product
角色属于框架这一方,是一个抽象类。它定义了在Factory Method
模式中生成的那些实例所持有的接口(API),但具体的处理则由子类ConcreteProduct
角色决定。在示例程序中,由Product
类扮演此角色。
Creator(创建者)
Creator
角色属于框架这一方,它是负责生成Product
角色的抽象类,但具体的处理则由子类ConcreteCreator
角色决定。在示例程序中,由Factory
类扮演此角色。
Creator
角色对于实际负责生成实例的ConcreteCreator
角色一无所知,它唯一知道的就是,只要调用Product
角色和生成实例的方法(create
),就可以生成Productde
的实例。在示例程序中,createProduct
方法是用于生成实例的方法。不用new
关键字来生成实例,而是调用生成实例的专用方法来生成实例,这样就可以防止父类与其他具体类耦合。
ConcreteProduct(具体产品)
ConcreteProduct
角色属于具体加工这一方,它决定了具体的产品。在示例程序中,由IDCard
类扮演此角色。
ConcreteCreator(具体的创建者)
ConcreteCreator
角色属于具体加工这一方,它负责生成具体的产品。在示例程序中,由IDCardFactory
类扮演此角色。
扩展思路
框架和具体加工
我们在实例程序中将程序分为了“框架”和“具体加工两个部分”,它们被封装在framework
和idcard
中。
在Factory Mothod
模式中我们可以使用相同的框架来创建出其它的“产品”和“工厂”。比如我们除了生产IDCart
外我们还可以使用相同的框架生成Television
的产品和工厂。我们只需要引入framework
中的包即可编写television
包。
也就是说,“framework”包并不依赖于具体实现的包。
相关的实例程序
Template Method
模式
Factory Method
模式是Template Method
的典型应用。在示例程序中,create
方法就是模板方法。
Singleton
模式
在多数情况下我们都可以将Singleton
模式用于扮演Creator
角色(或是ConcreteCreator
角色)的类。这是因为在程序中没有必要存在多个Creator
角色(或是ConcreteCreator角色)的实例。不过在示例程序中,我们并没有使用Singleton
模式。
Composite
模式
有时可以将Composite
模式用于Product
角色(或是ConcreteProduct
角色)。
Iterator
模式
tor角色(或是
ConcreteCreator角色)的类。这是因为在程序中没有必要存在多个
Creator角色(或是ConcreteCreator角色)的实例。不过在示例程序中,我们并没有使用
Singleton`模式。
Composite
模式
有时可以将Composite
模式用于Product
角色(或是ConcreteProduct
角色)。
Iterator
模式
有时,在Iterator
模式中使用iterator
方法生成Iterator
的实例时会使用Factory Method
模式。