目录
一、什么是工厂模式
我们在父类中规定处理的流程,在子类中实现具体的处理。如果我们将该模式用于生成实例,它就演变为工厂模式(FactoryMethod)。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
二、示例程序
1、Product
package com.as.module.factory;
/**
* 抽象产品类
* @author Andy
* @date 2021/4/24 17:31
*/
public abstract class Product {
public abstract void use();
}
2、Factory
package com.as.module.factory;
/**
* 抽象工厂类
* @author Andy
* @date 2021/4/24 17:32
*/
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);
}
3、IDCard
package com.as.module.factory;
/**
* 身份证类
* @author Andy
* @date 2021/4/24 17:35
*/
public class IDCard extends Product{
private String owner;
IDCard(String owner) {
System.out.println("制作"+owner+"的ID卡。");
this.owner = owner;
}
@Override
public void use() {
System.out.println("使用"+owner+"的ID卡。");
}
public String getOwner(){
return owner;
}
}
4、IDCardFactory
package com.as.module.factory;
import java.util.ArrayList;
import java.util.List;
/**
* 身份证工厂类
* @author Andy
* @date 2021/4/24 17:49
*/
public class IDCardFactory extends Factory{
private List owners = new ArrayList<>();
protected Product createProduct(String owner){
return new IDCard(owner);
}
@Override
protected void registerProduct(Product product) {
owners.add(((IDCard)product).getOwner());
}
public List getOwners(){
return owners;
}
}
5、TestFactory
package com.as.module.factory;
/**
* 工厂模式测试类
* @author Andy
* @date 2021/4/24 17:53
*/
public class TestFactory {
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();
}
}
运行结果:
三、UML图
登场角色
1、Product(产品)
Product角色属于框架这一方,是一个抽象类。它定义了在FactoryMethod模式中生成的那些实例所持有的接口(API),但具体的处理则由子类ConcreteProduct角色决定。在示例程序中,由Product类扮演此角色。
2、Creator(reator(创建者)
Creator角色属于框架这一方,它是负责生成Product角色的抽象类,但具体的处理则由子类ConcreteCreator角色决定。在示例程序中,由Factory类扮演此角色。
Creator角色对于实际负责生成实例的ConcreteCreator角色一无所知,它唯一知道的就是,只要调用Product角色和生成实例的方法,就可以生成Product的实例。在示例程序中,createProduct方法是用于生成实例的方法。不用new关键字来生成实例,而是调用生成实例的专用方法来生成实例,这样就可以防止父类和其它具体类耦合
3、ConcreteProduct(具体的产品)
ConcreteProduct角色属于加工这一方,它决定了具体的产品。在示例程序中,由IDCard类扮演此角色。
4、ConcreteCreator(具体的创建者)
ConcreteCreator角色属于具体加工这一方,它负责生成具体的产品。在示例程序中,由IDCardFactory类扮演此角色。
四、拓展思路与项目实战
1、框架与具体加工
这里,我们已经了解框架和具体加工的内容。我们可以用相同的框架再继续创建其他的“产品”和“工厂”。例如,我们这次要创建表示电视机的类Televeson和表示电视机工厂的类TelevionFactory。这时,我们只需要引入framework的包就可以编写televeson包。
我们没有也没有必要修改frameworkf包中的任何内容,就可以创建出其他的"产品"和“工厂”。
2、生成实例-方法的三种实现方式
(1) 指定其为抽象方法
指定其为抽象方法。一旦将createProductcreateProduct指定为抽象方法后,子类就必须实现该方法。‘
(2) 为其实现默认处理
实现默认处理后,如果子类没有实现该方法,将进行默认处理。
不过,这时是使用new关键字创建出实例的,因此不能将Product类定义为抽象类
(3) 在其中抛出异常
在其中抛出异常的方法。createProduct方法的默认处理为抛出异常,这样一来,如果未在子类中实现该方法,程序就会在运行时报错。不过需要,另外编写FactoryMethodRuntimeException异常类
3、使用模式与开发人员之间的沟通
实际开发过程中,如果仅阅读一个类的代码,是很难理解这个类的行为的。必须理解父类中所定义的框架和它里面所使用的抽象方法,然后阅读代码,了解这些抽象方法在子类中的实现才可以。
因此,在使用设计模式进行开发时,建议在注释中或者开发文档中记录使用设计模式的名称和意图,从而使后期的维护人员不会因不了解意图而违背最初的设计
4、产品具体实现类的构造方法非公开化
细心的同学可以看到IDCard类的构造函数并不是public,这样是想让idcard包外的类无法new出IDCard的实例,从而强迫外部必须通过IDCardFactoryardFactory来生成IdCard的实例