简单工厂模式
简单工厂模式:提供创建对象的功能,不需要关心具体的实现。
好处:降低客户端与模块之间的耦合度。
Android源码中的使用场景:BitmapFactory.decodeResource()
图:简单工厂模式类图
public interface Api {
void operator();
}
public class ImplA implements Api {
@Override
public void operator() {
System.out.println("完成了一种操作A");
}
}
public class ImplB implements Api {
@Override
public void operator() {
System.out.println("完成了一种操作B");
}
}
public class ImplC implements Api {
@Override
public void operator() {
System.out.println("完成了一种操作C");
}
}
public class Factory {
public static Api create(int type) {
switch (type) {
case 1:
return new ImplA();
case 2:
return new ImplB();
case 3:
return new ImplC();
default:
return new ImplC();
}
}
public static <T extends Api> T createProduct(Class<T> clz) {
Api api = null;
try {
api = (Api) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) api;
}
}
在工厂Factory中,我们可以有两种实现方式,一种根据不同的type来实例化对应的对象,一种通过反射获取对象。
Api api1 = Factory.create(1);
api1.operator();
Api api2 = Factory.createProduct(ImplA.class);
api2.operator();
输出:
完成了一种操作A
完成了一种操作A
工厂方法模式
工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类工厂方法使一个类的实例化延迟到创建器的子类中。
好处:扩展性强,父类代码的复用。
场景:CursorFactory,ArrayList,LayoutInflate等。
图:工厂方法模式图
工厂方法的通用模式代码
/**
* 抽象产品类
*/
public abstract class Product {
/**
* 产品类的抽象方法
* 由具体的产品类实现
*/
public abstract void method();
}
/**
* 具体产品A类
*/
public class ConcreteProductA extends Product {
@Override
public void method() {
System.out.println("我是具体的产品A");
}
}
/**
* 具体产品B类
*/
public class ConcreteProductB extends Product {
@Override
public void method() {
System.out.println("我是具体的产品B");
}
}
/**
* 抽象工厂类
*/
public abstract class Factory {
/**
* 抽象工厂方法
* 具体生产什么由子类去实现
*
* @return 具体的产品对象
*/
public abstract Product createProduct();
}
/**
* 具体工厂类
*/
public class ConcreteFactoryA extends Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
new ConcreteFactory().createProduct().method();
输出:
我是具体的产品A
这里得到的产品对象是ConcreteProductA的实例,想得到ConcreteProductB的实例,更改如下:
public class ConcreteFactoryB extends Factory {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
可以利用反射的方式更简洁地来生产具体产品对象,需要在工厂方法的参数列表中传入一个Class类来决定是哪一个产品类:
public abstract class ReflectFactory {
/**
* 抽象工厂方法
* 具体生产什么由子类去实现
*
* @param clazz 产品对象类类型
* @param <T>
* @return 具体的产品对象
*/
public abstract <T extends Product> T createProduct(Class<T> clazz);
}
具体的工厂类,则通过反射获取类的实例:
public class ReflectConcreteFactory extends ReflectFactory {
@Override
public <T extends Product> T createProduct(Class<T> clazz) {
Product product = null;
try {
product = (Product) Class.forName(clazz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) product;
}
}
实现:
ReflectFactory factory = new ReflectConcreteFactory();
factory.createProduct(ConcreteProductA.class).method();
factory.createProduct(ConcreteProductB.class).method();
输出:
我是具体的产品A
我是具体的产品B
像这样拥有多个工厂的方式称为工厂方法模式,如果工厂类只有一个,如下:
public class Factory {
public static Product createProduct() {
return new ConcreteProductA();
// return new ConcreteProductB();
}
}
这就是前面说到的简单工厂模式或者静态工厂模式,它是工厂方法模式的一个弱化版本。
工厂方法模式完全符合设计原则,其降低了对象之间的耦合度,工厂方式模式依赖于抽象的架构,其将实例化的任务交由子类去完成,有非常好的扩展性。
实例:开发一个导出数据的框架
- 确定的是:要导出数据做事情;
- 不确定的是:导出什么类型的文件。
实例:
/**
* 导出数据文件(数据文件可能有,数据库,文本,XML,Excel...pdf.未来)
*/
public interface ExportFileApi {
/**
* 导出文件
*
* @param data 需要导出的数据
* @return 是否成功
*/
boolean export(String data);
}
public abstract class ExportOperator {
//工厂方法:核心就是实例延迟到了子类去实现
public abstract ExportFileApi factoryMethod();
public boolean export(String data) {
ExportFileApi api = factoryMethod();
return api.export(data);
}
}
public class ExportTextFile implements ExportFileApi{
@Override
public boolean export(String data) {
System.out.println("数据:"+data);
System.out.println("导出生成了文本文件");
return true;
}
}
public class ExportTextFileOperator extends ExportOperator{
@Override
public ExportFileApi factoryMethod() {
return new ExportTextFile();
}
}
public class ExportDBFile implements ExportFileApi {
@Override
public boolean export(String data) {
System.out.println("数据:" + data);
System.out.println("导出生成了 数据库 文件");
return true;
}
}
public class ExportDBFileOperator extends ExportOperator {
@Override
public ExportFileApi factoryMethod() {
return new ExportDBFile();
}
}
//导出文本文件
ExportOperator operator = new ExportTextFileOperator();
operator.export("今天的财务报表");
//导出数据库文件
ExportOperator operator2 = new ExportDBFileOperator();
operator2.export("今天的财务报表2");
打印:
数据:今天的财务报表
类型:导出生成了 文本 文件
数据:今天的财务报表2
导出生成了 数据库 文件
示例中代码与uml图对应关系,如下所示:
简单工厂和工厂方法区别
两者区别从上图可以看出:工厂方法比简单工厂多了一个 工厂实现。
在简单工厂模式中,具体产品由工厂实现;
而在工厂方法模式中,具体产品由具体工厂实现。
抽象工厂模式
抽象工厂模式:简单工厂和工厂方法的一个组合体,最早应用于跨平台语言。
好处:选择产品簇的实现
场景:语言的跨平台实现,MediaPlayerFactory.cpp
/**
* 抽象产品类A
*/
public abstract class AbstractProductA {
/**
* 每个具体的产品子类需要实现的方法
*/
public abstract void method();
}
/**
* 抽象产品类B
*/
public abstract class AbstractProductB {
/**
* 每个具体的产品子类需要实现的方法
*/
public abstract void method();
}
/**
* 具体产品类A1
*/
public class ConcreteProductA1 extends AbstractProductA {
@Override
public void method() {
System.out.println("具体产品A1的方法");
}
}
/**
* 具体产品类A2
*/
public class ConcreteProductA2 extends AbstractProductA {
@Override
public void method() {
System.out.println("具体产品A2的方法");
}
}
/**
* 具体产品类B1
*/
public class ConcreteProductB1 extends AbstractProductB {
@Override
public void method() {
System.out.println("具体产品B1的方法");
}
}
/**
* 具体产品类B2
*/
public class ConcreteProductB2 extends AbstractProductB {
@Override
public void method() {
System.out.println("具体产品B2的方法");
}
}
/**
* 抽象工厂类
*/
public abstract class AbstractFactory {
/**
* 创建产品A的方法
*
* @return 产品A对象
*/
public abstract AbstractProductA createProductA();
/**
* 创建产品B的方法
*
* @return 产品B对象
*/
public abstract AbstractProductB createProductB();
}
/**
* 具体工厂类1
*/
public class ConcreteFactory1 extends AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
}
/**
* 具体工厂类2
*/
public class ConcreteFactory2 extends AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB2();
}
}
new ConcreteFactory1().createProductA().method();
new ConcreteFactory1().createProductB().method();
new ConcreteFactory2().createProductA().method();
new ConcreteFactory2().createProductB().method();
具体产品A1的方法
具体产品B1的方法
具体产品A2的方法
具体产品B2的方法
抽象工厂方法模式的类主要分为4类:
-
AbstractFactory:抽象工厂角色,它声明了一组用于创建一种产品的方法,每一个方法对应一种产品,这里AbstractFactory中分别定义了创建产品A和产品B的方法。
-
ConcreteFactory:具体工厂角色,它实现了抽象工厂中定义的创建产品的方法,生成一组具体产品。
-
AbstractProduct:抽象产品角色,它为每中产品声明接口。
-
ConcreteProduct:具体产品角色,它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。
抽象工厂方法模式示例
public interface IFactory {
IButtonApi createButton(int type);
ITextViewApi createTextView(int type);
}
public interface IButtonApi {
void show();
}
public interface ITextViewApi {
void show();
}
public class IOSButtonApi implements IButtonApi {
@Override
public void show() {
System.out.println("IOS Button API产出");
}
}
public class AndroidTextViewApi implements ITextViewApi {
@Override
public void show() {
System.out.println("Android TextView API产出");
}
}
public class AndroidButtonApi implements IButtonApi {
@Override
public void show() {
System.out.println("Android Button API产出");
}
}
public class IOSTextViewApi implements ITextViewApi {
@Override
public void show() {
System.out.println("IOS TextView API产出");
}
}
public class IOSFactory implements IFactory {
@Override
public IButtonApi createButton(int type) {
return new IOSButtonApi();
}
@Override
public ITextViewApi createTextView(int type) {
return new IOSTextViewApi();
}
}
public class AndroidFactory implements IFactory {
@Override
public IButtonApi createButton(int type) {
if (type == 1) {
return new AndroidButtonApi();
}
return null;
}
@Override
public ITextViewApi createTextView(int type) {
return new AndroidTextViewApi();
}
}
int i = 1;
if (i == 1) {
new IOSFactory().createButton(1).show();
new IOSFactory().createTextView(1).show();
// MediaPlayer m = new MediaPlayer();
} else if (i == 2) {
new AndroidFactory().createButton(1).show();
new AndroidFactory().createTextView(1).show();
}
IOS Button API产出
IOS TextView API产出
抽象工厂 由 多个工厂方法组成
示例代码对应uml图中的位置,如下: