Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)
工厂模式是经常用到的设计模式之一。其作用是,延迟子类初始化,客户端只需从工厂中获取产品,而不用了解产品生产的细节,降低了模块之间的耦合。也是面向接口编程体现。
图片摘自HeadFirst
从类图上看,有产品接口,制造者也就是工厂接口。具体产品实现产品接口,具体工厂实现工厂接口。然后工厂的实现类,关联具体的产品。为了更好地理解这个模式,敲了一个小例子,加以辅助,希望可以取得一些助攻。【深入了解这个模式可以参考 《设计模式之禅》 和《HeadFirst》 这两本书都是良心之作 文档下载见参考资料】
例子背景:有个平板工厂,工厂可以生产苹果平板,安卓平板。平板可以连接wifi关闭wifi等功能。
例子类图如下:
PAD接口代码:
package phlin.samples.factory.pad;
public interface PAD {
/**
* 联网功能
*/
public void linkToNet();
/**
* 打开wifi功能
*/
public void openWifi();
/**
* 关闭wifi功能
*/
public void closeWifi();
/**
* other functions
*/
}
工厂接口代码:
package phlin.samples.factory.pad;
/**
* 平板 工厂 接口
* @author lin
*
*/
public interface PADFactoryI {
public PAD createPad(String padType);
}
安卓平板代码:【实现平板接口】
package phlin.samples.factory.pad;
public class AndroidPad implements PAD {
@Override
public void linkToNet() {
// TODO Auto-generated method stub
UtilClass.Dis("I use a android pad to get msg from Intener");
}
@Override
public void openWifi() {
// TODO Auto-generated method stub
UtilClass.Dis("open android pad wifi");
}
@Override
public void closeWifi() {
// TODO Auto-generated method stub
UtilClass.Dis("close android pad wifi");
}
}
苹果平板代码:【实现平板接口】
package phlin.samples.factory.pad;
public class IOSPad implements PAD{
@Override
public void linkToNet() {
// TODO Auto-generated method stub
UtilClass.Dis("I use a IOS pad to get msg from Intener");
}
@Override
public void openWifi() {
// TODO Auto-generated method stub
UtilClass.Dis("open IOS pad wifi");
}
@Override
public void closeWifi() {
// TODO Auto-generated method stub
UtilClass.Dis("close IOS pad wifi");
}
}
工厂实现代码:【实现工厂接口】
package phlin.samples.factory.pad;
public class PadFactory implements PADFactoryI{
PAD pad=null;
@Override
public PAD createPad(String padType) {
// TODO Auto-generated method stub
if(padType.equals("android"))
{
pad=new AndroidPad();
}else if(padType.equals("iso"))
{
pad=new IOSPad();
}else
{
UtilClass.Dis("no instance");
}
return pad;
}
}
辅助显示类:
package phlin.samples.factory.pad;
public final class UtilClass {
/**
* 终端显示
* @param str
*/
public static void Dis(String str)
{
System.out.println(str);
}
}
测试类代码:
package phlin.samples.factory.pad;
public class TestClass {
public static void main(String[] args) {
PAD andPad=null,iosPad=null;
//pad工厂实例化
PadFactory factory=new PadFactory();
//生产安卓平板
andPad=factory.createPad("android");
andPad.linkToNet();
//生产苹果平板
iosPad=factory.createPad("iso");
iosPad.linkToNet();
}
}
测试结果:
I use a android pad to get msg from Intener
I use a IOS pad to get msg from Intener
可以发现。测试类代码中只需实例化工厂,然后通过createPad方法 就可以实例化相对应的平板,而且,关键是,测试类中,无需关系平板是如何生产的,极大降低了模块直接耦合,有利于拓展。
但是这种通过 String padType 的方式来判断那类产品要生产,似乎比较麻烦,如果款式比较多,还得一个个加。这里有一种比较好的优化方案,用泛型来实现,直接通过类名来实例化子类。
下面对工厂接口和工厂实现类做一些改动:
注意不同之处:
工厂接口:
package phlin.samples.factory.pad;
/**
* 平板 工厂 接口
* @author lin
*
*/
public interface PADFactoryI {
public <T extends PAD> T ceratePad(Class <T> c);
}
工厂实现类:
package phlin.samples.factory.pad;
public class PadFactory implements PADFactoryI{
PAD pad=null;
@Override
public <T extends PAD> T ceratePad(Class<T> c) {
// TODO Auto-generated method stub
PAD pad=null;
try {
pad=(PAD)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
// TODO: handle exception
}
return (T)pad;
}
}
测试类代码:
package phlin.samples.factory.pad;
public class TestClass {
public static void main(String[] args) {
PAD andPad=null,iosPad=null;
PadFactory factory=new PadFactory();
andPad=factory.ceratePad(AndroidPad.class);
andPad.linkToNet();
iosPad=factory.ceratePad(IOSPad.class);
iosPad.linkToNet();
}
}
测试结果:
I use a android pad to get msg from Intener
I use a IOS pad to get msg from Intener
测试结果一样,但是对于工厂实现类,要添加新类型产品是,该类几乎不用改动。对于产品,只需拓展产品也就是平板类型即可。
设计模式之禅
HeadFirst
资料链接:http://pan.baidu.com/s/1i3rfm9B 密码:6q98
转载注明出处:http://blog.csdn.net/androidolblog/article/details/46275725
有所不足,多多指正,谢谢!
原文地址:http://blog.csdn.net/androidolblog/article/details/46275725