1工厂模式介绍
在面向对象编程中,继承是一个基本概念,它与多态共同构成了类的父子继承关系(Is-A关系)。在大多数情况下,最棘手的问题往往是对象的创建。在面向对象编程中,每个对象都使用特定类的构造器进行实例化操作,但是这种情况耦合度较高,所以需要解耦
定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
核心类:产品类和工厂类
产品类(Product):抽象产品类负责定义产品的共性,实现对事物最抽象的定义
工厂类:抽象工厂是抽象创建类,负责创建产品类的实例
2简单工厂类
场景:创建各个国家的人
特征:比较好理解,简单易操作(在工厂类里一顿if else)
类图
代码
产品族
// 产品类 创建的产品只需要实现该接口
public interface Human {
//每个国家饮食习惯不同
public void eat();
//每个国家类说话的语种
public void talk();
}
public class ChinaHuman implements Human {
@Override
public void eat() {
System.out.println("中国人饮食文化");
}
public void talk() {
System.out.println("中国人说汉语");
}
}
public class AmericanHuman implements Human {
@Override
public void eat() {
System.out.println("美国人饮食文化");
}
public void talk() {
System.out.println("美国人说英语");
}
}
工厂类
//工厂类
public class HumanFactory {
public static Human createHuman(String type) {
Human human = null;
if ("China".equals(type)) {
human = new ChinaHuman();
} else if ("American".equals(type)) {
human = new AmericanHuman();
}//有其他国家的人时,在这里继续添加
return human;
}
}
调用client类
public class FactoryClient {
public static void main(String[] args) {
FactoryClient nvWaClient = new FactoryClient();
String chinaHumanType = "China";
Human chinaHuman = HumanFactory.createHuman(chinaHumanType);
chinaHuman.eat();
chinaHuman.talk();
String yamericaHumanType = "American";
Human americaHuman = HumanFactory.createHuman(yamericaHumanType);
americaHuman.eat();
americaHuman.talk();
}
}
3升级版工厂模式
上面代码工厂类里不满足ocp开闭原则,所以需要对工厂族进行修改扩展,
工厂族的代码为
// 抽象人类创建工厂,采用泛型对输入参数进行限制
public abstract class AbstractHumanFactory {
public abstract <T extends Human> T createHuman(Class<T> c);
}
public class HumanFactory extends AbstractHumanFactory{
public <T extends Human> T createHuman(Class<T> c){
//定义一个国家的人类
Human human=null;
try {
//产生个国家的人类
human = (T)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
System.out.println("人类生成错误!");
}
return (T)human;
}
}
调用Client类
public class HumanFactoryClient {
public static void main(String[] args) {
//声明工厂类
AbstractHumanFactory humanFactory = new HumanFactory();
System.out.println("--创建中国人--");
ChinaHuman chinaHuman = humanFactory.createHuman(ChinaHuman.class);
chinaHuman.eat();
chinaHuman.talk();
System.out.println("--创建美国人--");
AmericanHuman americanHuman = humanFactory.createHuman(AmericanHuman.class);
americanHuman.eat();
americanHuman.talk();
}
}
上述代码,扩展性较高,当定义其他国家的人类时,直接实现Human接口
4通用源码
在工厂方法模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象的定义;Creator为抽象创建类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的。工厂方法模式的变种较多,下面是一个通用源码
//抽象产品类
public abstract class Product {
//产品类的公共方法
public void method1(){
//业务逻辑处理
}
//抽象方法
public abstract void method2();
}
public class ConcreteProduct1 extends Product{
public void method2() {
//业务逻辑处理
}
}
public class ConcreteProduct2 extends Product{
@Override
public void method2() {
//业务逻辑处理
}
}
public abstract class Creator {
/*
* 创建一个产品对象,其输入参数类型可以自行设置
* 通常为String、Enum、Class等,当然也可以为空
*/
public abstract <T extends Product> T createProduct(Class<T> c);
}
public class ConcreteCreator extends Creator{
public <T extends Product> T createProduct(Class<T> c){
Product product=null;
try {
product = (Product)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
//异常处理
}
return (T)product;
}
}
public class Client {
public static void main(String[] args) {
Creator creator = new ConcreteCreator();
Product product = creator.createProduct(ConcreteProduct1.class);
/*
* 继续业务处理
*/
}
}
总结:
首先,工厂方法模式是new一个对象的替代品,所以在所有需要生成对象的地方都可以使用,但是需要慎重地考虑是否要增加一个工厂类进行管理,增加代码的复杂度。
其次,需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式。
屏蔽产品类,通过工厂族去创建产品实例,上述代码只是一个出版,根据业务需求可以细化工厂类的家族(添加中国人工厂类,美国人工厂类等等),
工厂模式和其他设计模式(例如模板方法模式、单例模式、原型模式等)组合来完成自己的需求