目录
回顾简单工厂模式
可以参考我的另一篇博客
工厂类角色LightSimpleFactory:在客户端的直接控制下创建产品对象。
抽象产品角色Light:定义简单工厂创建的对象的父类或它们的接口。可以是一个类、抽象类或接口。
具体产品角色BulbLight, TubeLight:具体产品对象。
- 优点:工厂类中有必要的逻辑判断,根据客户端的选择,动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖
- 缺点:在某种程度上违背了开放–封闭原则。对工厂类过于依赖,一旦工厂类出现问题,所有程序都会出现问题
因此,推出了工厂方法模式
工厂方法模式
实质:延迟到子类来选择实现
目的:定义一个创建产品对象的工厂接口,将具体创建工作放到具体工厂子类中。
允许在不修改工厂角色的情况下引进新产品。
具体产品由具体工厂创建,往往一一对应。
抽象工厂(Creator)角色:
核心,与应用程序无关。所有具体工厂类都要实现这个接口。
方法中指向抽象产品类
具体工厂(Concrete Creator)角色:
实现抽象工厂接口。包含与应用程序相关的逻辑,受应用程序调用来创建不同的产品对象。图中:BulbCreator与TubeCreator。
方法中指向具体产品类
抽象产品(Product)角色:
Light
具体产品(Concrete Product)角色:
BulbLight,TubeLight
示例代码:
(1)抽象产品角色:
public abstract class Light {
public abstract void TurnOn();
public abstract void TurnOff();
}
(2)具体产品角色:
public class BulbLight extends Light{
@Override
public void TurnOn() {
System.out.println("电灯泡亮了");
}
@Override
public void TurnOff() {
System.out.println("电灯泡灭了");
}
}
public class TubeLight extends Light{
@Override
public void TurnOn() {
System.out.println("管道亮了");
}
@Override
public void TurnOff() {
System.out.println("管道暗了");
}
}
(3)抽象工厂角色:
public abstract class Creator {
//指向具体产品类
public abstract Light factory();
}
(4)具体工厂角色:
public class BulbCreator extends Creator{
@Override
public Light factory() {
return new BulbLight();
}
}
public class TubeCreator extends Creator{
@Override
public Light factory() {
return new TubeLight();
}
}
简单测试一下:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
System.out.println("请输入1 or 2");
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
if(n==1) {
Creator c1=new BulbCreator();
Light l1=c1.factory();
l1.TurnOn();
l1.TurnOff();
}else {
Creator c2=new TubeCreator();
Light l2=c2.factory();
l2.TurnOn();
l2.TurnOff();
}
cin.close();
}
}
工厂方法模式很好的体现了“依赖倒置原则”, 依赖倒置原则告诉我们“要依赖抽象,不要依赖于具体类”,也就是:不能让高层组件依赖于低层组件,而且不管高层组件还是低层组件,都应该依赖于抽象。
- 对于抽象工厂来说,它不关心具体的实现方式,它只是“面向接口编程”
- 对于具体的实现来说,它只关心自己“如何实现接口”所要求的功能。
优缺点
克服了简单工厂模式一些缺点,保留了简单工厂模式的优点。
优点:
需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象。原有工厂对象不需要进行任何修改,也不需要修改客户端,较好的符合了“开放-封闭”原则。
而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。
缺点:
具体产品对象与工厂方法的耦合性高。
工厂方法需要选择具体的产品对象,并创建他们的实例。因此具体产品对象与工厂方法是耦合的。
工厂方法模式VS简单工厂模式
二者在结构上大同小异。
但工厂方法类的核心是一个抽象工厂类,而简单工厂模式的核心是一个具体类。
工厂方法模式又叫多态性工厂模式,因为具体工厂类都有共同的接口,或者有共同的抽象父类。
应用场景
工厂方法模式:如果一个类需要创建某个类的对象,但是又不知道具体的实现,可以选用工厂方法模式,把创建对象的工作延迟到子类中实现。
简单工厂模式:一个类想要把对外创建对象的职责集中管理和控制
实例
用工厂方法模式实现计算器
public abstract class Operation {
protected double numberA=0;
protected double numberB=0;
public double getNumberA() {
return numberA;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
public double getResult() {
double result=0;
return result;
}
}
public class OperationAdd extends Operation{
public double getResult() {
double result=0;
result=numberA+numberB;
return result;
}
}
public class OperationSub extends Operation{
public double getResult() {
double result=0;
result=numberA-numberB;
return result;
}
}
public class OperationMul extends Operation{
public double getResult() {
double result=0;
result=numberA*numberB;
return result;
}
}
public class OperationDiv extends Operation{
public double getResult() {
double result=0;
if(numberB==0)
result=numberA/numberB;
return result;
}
}
public interface OperationFactory {
public abstract Operation createOperation() ;
}
public class AddFactory implements OperationFactory{
@Override
public Operation createOperation() {
return new OperationAdd();
}
}
public class SubFactory implements OperationFactory{
@Override
public Operation createOperation() {
// TODO Auto-generated method stub
return new OperationSub();
}
}
public class MulFactory implements OperationFactory{
@Override
public Operation createOperation() {
// TODO Auto-generated method stub
return new OperationMul();
}
}
public class DivFactory implements OperationFactory{
@Override
public Operation createOperation() {
// TODO Auto-generated method stub
return new OperationDiv();
}
}
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
System.out.println("请输入两个操作数,再输入一个运算符:");
Scanner cin=new Scanner(System.in);
int a=cin.nextInt();
int b=cin.nextInt();
String s=cin.next();
//此处只检验加减
if(s.equals("+")) {
OperationFactory of1=new AddFactory();
Operation o1=of1.createOperation();
o1.setNumberA(a);
o1.setNumberB(b);
System.out.println(o1.getResult());
}else {
OperationFactory of2=new SubFactory();
Operation o2=of2.createOperation();
o2.setNumberA(a);
o2.setNumberB(b);
System.out.println(o2.getResult());
}
cin.close();
}
}
导出数据
各分公司内运行系统独立,每天业务结束时,各分公司导出业务数据、打包、传送给总公司。
导出数据格式会有不同要求:文本格式、数据库备份格式、Excel格式、Xml格式
分清哪是产品类、哪是工厂类
产品类:
public abstract class Export {
public abstract void export(String data);
}
public class ExportDB extends Export{
@Override
public void export(String data) {
System.out.println("以DB方式导出业务数据"+data);
}
}
public class ExportExcel extends Export{
@Override
public void export(String data) {
System.out.println("以excel导出业务数据"+data);
}
}
public class ExportText extends Export{
@Override
public void export(String data) {
System.out.println("以文本导出业务数据"+data);
}
}
public class ExportXml extends Export{
@Override
public void export(String data) {
System.out.println("以xml方式导出业务数据"+data);
}
}
工厂类:
public interface FrimFactory {
public Export exportFile();
}
public class TextFactory implements FrimFactory{
@Override
public Export exportFile() {
// TODO Auto-generated method stub
return new ExportText();
}
}
public class ExcelFactory implements FrimFactory{
@Override
public Export exportFile() {
// TODO Auto-generated method stub
return new ExportExcel();
}
}
public class DBFactory implements FrimFactory{
public ExportDB exportFile() {
return new ExportDB();
}
}
public class XmlFactory implements FrimFactory{
@Override
public Export exportFile() {
// TODO Auto-generated method stub
return new ExportXml();
}
}
public class Test {
public static void main(String[] args) {
FrimFactory f1=new DBFactory();
Export e1=f1.exportFile();
e1.export("data1");
FrimFactory f2=new TextFactory();
Export e2=f2.exportFile();
e2.export("data2");
}
}