小明开发的应用,经常要从XML或者Asset中读取省市区数据。
小明是这样写的:
public abstract class IOHandler {
/**
* 添加
*/
public abstract void add(String id, String name);
/**
* 删除
*/
public abstract void remove(String id);
/**
* 修改
*/
public abstract void update(String id, String name);
/**
* 查询
*/
public abstract String query(String id);
}
public class XMLHandler extends IOHandler {
@Override
public void add(String id, String name) {
//业务处理
}
@Override
public void remove(String id) {
//业务处理
}
@Override
public void update(String id, String name) {
//业务处理
}
@Override
public String query(String key) {
return "xml";
}
}
public class AssetHandler extends IOHandler {
@Override
public void add(String id, String name) {
//业务处理
}
@Override
public void remove(String id) {
//业务处理
}
@Override
public void update(String id, String name) {
//业务处理
}
@Override
public String query(String name) {
return "asset";
}
}
public void test() {
IOHandler asset = new AssetHandler();
String result = asset.query("city.txt");
System.out.println("result:" + result);
IOHandler xml = new XMLHandler();
result = xml.query("city");
System.out.println("result:" + result);
}
输出结果
result:asset
result:xml
小明的领导一看,说这样写不行,如果AssetHandler换一种实现方式,岂不是每个引用的地方都要改变?假如以后不想通过这些方式读取城市数据,要增加一个读取本地文件的方式,改动起来很不方便。
领导说生成这种具有相同功能的对象,可以使用工厂模式。
小明觉定用简单工厂尝试改造,增加一个工厂来负责生成对象
public class SimpleFactory {
public IOHandler getHandler(String type) {
IOHandler ioHandler = null;
switch (type) {
case "xml":
ioHandler = new XMLHandler();
break;
case "asset":
ioHandler = new AssetHandler();
break;
default:
break;
}
return ioHandler;
}
}
public void test() {
SimpleFactory factory = new SimpleFactory();
IOHandler asset = factory.getHandler("asset");
String result = asset.query("city.txt");
System.out.println("result:" + result);
IOHandler xml = factory.getHandler("xml");
result = xml.query("city");
System.out.println("result:" + result);
}
小明的领导一看,如果要增加新的对象,或者增加一些业务逻辑,岂不是要修改工厂,工厂因此变得复杂和臃肿。
小明决定使用工厂方法改造:
public class AssetFactory implements IFactory {
@Override
public IOHandler getHandler() {
return new AssetHandler();
}
}
public class XMLFactory implements IFactory {
@Override
public IOHandler getHandler() {
return new XMLHandler();
}
}
public void test() {
IFactory assetFactory = new AssetFactory();
IFactory xmlFactory = new XMLFactory();
IOHandler asset = assetFactory.getHandler();
String result = asset.query("city.txt");
System.out.println("result:" + result);
IOHandler xml = xmlFactory.getHandler();
result = xml.query("city");
System.out.println("result:" + result);
}
和简单工厂不同的是,工厂方法是多工厂,每个工厂负责生成一个对象。如果要增加新的对象,只需要增加一个工厂即可,具有良好的扩展性。
工厂方法模式是简单工厂演化而来的高级版,后者才是真正的设计模式。
假如情景更复杂呢?
比如说之前的工厂都是小明写的,但不好用,新来的程序员小张想用自己写的呢?
我有那么多工厂,我想要一个超级工厂,去管理这些工厂呢?
这时候就可以用抽象工厂了:
小明写的Handler:
public class XiaomingAssetHandler extends IOHandler {
@Override
public void add(String id, String name) {
//业务处理
}
@Override
public void remove(String id) {
//业务处理
}
@Override
public void update(String id, String name) {
//业务处理
}
@Override
public String query(String name) {
return "xiaoming asset";
}
}
public class XiaomingXMLHandler extends IOHandler {
@Override
public void add(String id, String name) {
//业务处理
}
@Override
public void remove(String id) {
//业务处理
}
@Override
public void update(String id, String name) {
//业务处理
}
@Override
public String query(String key) {
return "xiaoming xml";
}
}
小张写的Handler
public class XiaozhangAssetHandler extends IOHandler {
@Override
public void add(String id, String name) {
//业务处理
}
@Override
public void remove(String id) {
//业务处理
}
@Override
public void update(String id, String name) {
//业务处理
}
@Override
public String query(String name) {
return "xiaozhang asset";
}
}
public class XiaozhangXMLHandler extends IOHandler {
@Override
public void add(String id, String name) {
//业务处理
}
@Override
public void remove(String id) {
//业务处理
}
@Override
public void update(String id, String name) {
//业务处理
}
@Override
public String query(String key) {
return "xiaozhang xml";
}
}
创建抽象工厂
public interface AbstractFactory {
IOHandler getXMLHandler();
IOHandler getAssetHandler();
}
创建小明的具体工厂
class XianmingFactory implements AbstractFactory{
@Override
public IOHandler getXMLHandler() {
return new XiaomingXMLHandler();
}
@Override
public IOHandler getAssetHandler() {
return new XiaomingAssetHandler();
}
}
创建小张的具体工厂
class XianzhangFactory implements AbstractFactory{
@Override
public IOHandler getXMLHandler() {
return new XiaozhangXMLHandler();
}
@Override
public IOHandler getAssetHandler() {
return new XiaozhangAssetHandler();
}
}
创建超级工厂
public class FactoryProducer {
public AbstractFactory getFactory(String type) {
AbstractFactory factory = null;
switch (type) {
case "xiaoming":
factory = new XianmingFactory();
break;
case "xiaozhang":
factory = new XianzhangFactory();
break;
default:
break;
}
return factory;
}
}
开始测试
public void test() {
FactoryProducer factoryProducer = new FactoryProducer();
//创建小明工厂
AbstractFactory xiaomingFactory = factoryProducer.getFactory("xiaoming");
//创建小张工厂
AbstractFactory xiaozhangFactory = factoryProducer.getFactory("xiaozhang");
//使用小明写的Asset读取方式
IOHandler ioHandler = xiaomingFactory.getAssetHandler();
String result = ioHandler.query("city.txt");
System.out.println("result:" + result);
//使用小张写的Asset读取方式
ioHandler = xiaozhangFactory.getAssetHandler();
result = ioHandler.query("city.txt");
System.out.println("result:" + result);
}
输出结果
result:xiaoming asset
result:xiaozhang asset
可以看到,抽象工厂最核心的是,多工厂,多产品的思路。
比如说富士康在深圳和东莞都有厂,都生产手机和电脑。区别是,深圳生产华为手机和华为电脑,东莞生产苹果手机和苹果电脑。
又比如说游戏里面,角色类型有人族和兽族,角色等级又有低中高级,人族和兽族就是工厂,各自生产低中高级的角色。
看一下工厂方法模式的UML图
有多个工厂,每个工厂生产多个产品
简单工厂:一个工厂方法生产多个产品
工厂方法:多个具体工厂,一个工厂生产一个产品
抽象工厂:多个具体工厂,一个工厂生产多个产品
拿刚刚游戏里面打比方,简单工厂不符合设计模式规范,而使用工厂方法就要写6个工厂之多,这时候使用抽象工厂就非常适合了。
工厂设计模式的核心是:生产产品
什么才叫产品?
比如说自定义的Button,有圆角的,直角的,圆形的
比如说通知栏样式的适配,根据不同的Android系统版本配置不同的样式
比如应用的主题,有深色的、浅色的,主题要配置button、textview、dialog等控件
比如应用的语言,有中文的、英文的
…
这些都是产品,它们的本质是一样的,但形态又不同。
如果仔细观察,应用内很多地方其实是可以用上工厂设计模式的