工厂方法定义
以下内容引用GOF所著《Design Patterns》的中译本及英文版。
工厂方法模式(别名:虚拟构造)
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
MediatorPattern(Another Name:Virtual Constructor)
Define an interface for creationg an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.
为什么要使用工厂方法
- 使用工厂方法可以让用户的代码和某个特定类的子类的代码解耦。
- 工厂方法使用户不必知道它所使用的对象是怎样被创建的,只需要知道该对象有那些方法即可。
如何使用工厂方法
1.工厂方法组成
- 抽象产品(Product):抽象类或者接口,负责定义具体产品必须实现的方法。
- 具体产品(ConcreteProduct):具体产品是一个类,如果Product是一个接口,那么具体产品是实现该接口的类,如果Product是一个抽象类,那么具体产品是该抽象类的子类。
- 构造者(Creator):一个接口或者抽象类。构造者负责定义一个称作工厂方法的抽象方法,改方法返回抽象产品类的实例。
- 具体构造者(ConcreteCreator):如果构造者是抽象类,具体构造者是构造者的子类;如果构造者是接口,具体构造者是实现构造者的类。具体构造者重写工厂方法使该方法返回具体产品的实例。
2.工厂方法的关键点
- 工厂方法模式的关键是在一个接口或者抽象类中定义一个抽象方法,该方法返回某个类的子类的实例,该抽象类或者接口让其子类或者实现该接口的类通过重写这个抽象方法返回某个子类的实例。
- 应用程序在使用工厂模式时,只和抽象产品、构造者以及具体构造者打交道用户只需了解产品有那些方法即可,不需要知道有那些具体产品。
3.工厂方法UML类图
代码实例
- 我们要创建一个Shape接口和实现Shape接口的具体类。 我们的演示类将使用ShapeFactory获得一个Shape对象。 它会传递信息( 圆/矩形),以ShapeFactory得到它所需要的对象的类型。
第一个步,创建shape抽象类,也就是我们提到的抽象产品。
package cn.com.java.design.pattern.Shape;
/**
* Created by Administrator on 2016/3/3.
*/
public abstract class Shape {
public abstract void draw();
}
第二步,创建具体的产品,这里创建了两个具体产品,矩形和圆形。
package cn.com.java.design.pattern.Shape;
/**
* Created by Administrator on 2016/3/3.
*/
public class Rectangle extends Shape {
@Override
public void draw() {
System.out.println("我画出了矩形图");
}
}
/**
* Created by Administrator on 2016/3/3.
*/
public class Circle extends Shape {
@Override
public void draw() {
System.out.println("我画出了圆形图案!");
}
}
第三步,实现工厂方法
package cn.com.java.design.pattern.Shape;
/**
* Created by Administrator on 2016/3/3.
*/
public class ShapeFactory {
public Shape getShape(String name){
if(name.isEmpty())
return null;
else if(name.equalsIgnoreCase("rectangle")){
return new Rectangle();
}else if(name.equalsIgnoreCase("circle")){
return new Circle();
}
return null;
}
}
第四步,测试方法
public class Main {
public static void main(String[] args) {
System.out.println("------开始练习工厂方法 采用形状案例------");
ShapeFactory shape=new ShapeFactory();
shape.getShape("CIRCLE").draw();
shape.getShape("rectangle").draw();
System.out.println("------结束练习工厂方法 采用形状案例------");
}
}
打印输出为:
——开始练习工厂方法 采用形状案例——
我画出了圆形图案!
我画出了矩形图
——结束练习工厂方法 采用形状案例——
2 . 我们要创建一个Drug(药物)接口和实现Drug接口的具体类。同时创建一个DrugCreator(药物构造者)接口和实现DrugCreator接口的DrugCreatorImpl(具体药物构造者),通过它们来创造出具体药物的产品实例。
第一步,创建抽象的药物接口Drug
package cn.com.java.design.pattern.Drug;
/**
* Created by LY on 2016/3/3.
*/
public interface Drug {
//药物具体说明
void getDugDeclare();
}
第二步,创建2个实现Drug的具体类Amorolfine和Paracetmol
package cn.com.java.design.pattern.Drug;
/**
* Created by Administrator on 2016/3/3.
*/
public class Amorolfine implements Drug {
String part1="组成部分一";
String part2="组成部分二";
String name="amorolfine药物";
public void amorolfineToString() {
System.out.println(name+" 组成是有:"+part1+","+part2+" .而组成!");
}
@Override
public void getDugDeclare() {
amorolfineToString();
}
}
package cn.com.java.design.pattern.Drug;
/**
* Created by Administrator on 2016/3/3.
*/
public class Paracetmol implements Drug {
String part1="组成部分一";
String part2="组成部分二";
String part3="组成部分三";
String name="paracetmol药物";
public void paracetmolToString() {
System.out.println(name+" 组成是有:"+part1+","+part2+","+part3+" .而组成!");
}
@Override
public void getDugDeclare() {
paracetmolToString();
}
}
第三步,创建药物构造者接口DrugCreator
package cn.com.java.design.pattern.Drug;
/**
* Created by Administrator on 2016/3/3.
*/
public interface DrugCreator {
Drug getParacetmol();
Drug getAmorolfine();
}
第四步,创建实现药物构造者接口的实体类DrugCreatorImpl
package cn.com.java.design.pattern.Drug;
/**
* Created by Administrator on 2016/3/3.
*/
public class DrugCreatorImpl implements DrugCreator {
@Override
public Drug getParacetmol() {
return new Paracetmol();
}
@Override
public Drug getAmorolfine() {
return new Amorolfine();
}
}
第五步,测试
public class Main {
public static void main(String[] args) {
System.out.println("------开始练习工厂方法 采用药物案例------");
DrugCreator drugCreator=new DrugCreatorImpl();
drugCreator.getAmorolfine().getDugDeclare();
drugCreator.getParacetmol().getDugDeclare();
System.out.println("工厂方法把父类与子类很好的解耦,只暴漏出父类接口,子类的具体 实现不用关心。只要调用相应的方法,就会自动实例化");
System.out.println("------结束练习工厂方法 采用药物案例------");
}
}
输出为:
——开始练习工厂方法 采用药物案例——
amorolfine药物 组成是有:组成部分一,组成部分二 .而组成!
paracetmol药物 组成是有:组成部分一,组成部分二,组成部分三 .而组成!
工厂方法把父类与子类很好的解耦,只暴漏出父类接口,子类的具体 实现不用关心。只要调用相应的方法,就会自动实例化
——结束练习工厂方法 采用药物案例——