工厂方法模式定义
定义一个用于创建对象的接口,让子类决定实例化那个类
工厂方法模式
1.简单工厂模式
简单工厂模式的工厂类一般使用静态方法,方法通过接收的参数不同返回创建不同产品对象。
举一个例子:
比如我喜欢去超市买水果:我抽象出来一个水果抽象类:
public abstract class Fruit{
public abstract void desc();
}
下班后去超市逛逛,看超市的水果,看价格挑选,看上那个水果就超市就给你拿那个这里具体实现几个水果对象:
public class Apple extends Fruit(){
public void desc(){
System.out.print("红红的苹果。");
}
}
public class Orange extends Fruit(){
public void desc(){
System.out.print("大大的橘子");
}
}
去超市买水果,把超市抽象wei一个工厂类Market:
public class Market{
public static final int APPLE = 1;
public static final int ORANGE = 2;
public static Fruit createFruit(int type){
switch(type){
case APPLE:
return new Apple();
case ORANGE:
return new Orange();
default :
return null;
}
}
}
简单的工厂类,你说要啥它就给你提供啥,
Fruit apple = Market.createFruit(Market.APPLE);
apple.desc();
输出
红红的苹果
这就是简单的工厂类,你要什么他就给你提供什么,
优点是:低耦合,简单
缺点:如果要添加新的产品类,工厂创建方法也要改变,创建出新的产品对象,这不符合软件开发的六大原则之开闭原则。
通过改进可以把Market类里面创建对象的方法,通过反射实现。
public static <T extends Fruit> T createFruit(Class<T> clz){
T result = null;
try{
result = Class.forName(clz.getName()).newInstance();
}catch(Exception e){
e.printStackTrace();
}
return result;
}
得到橘子:
Fruit orange = Market.createFruit(Orange.class);
orange.desc();
这样创建的优点是,当新增产品类(水果),只有继承Fruit抽象类就可以,不用修改工厂类Market。符合软件开发的原则之开闭原则,对类继承扩展是开放的,对于修改是关闭的。
缺点是反射效率低,创建对象是调用的无参数构造函数。对于类需要有参来初始化,这个方法不适合。
2.工厂方法模式
多方法的工厂模式为不同的产品,提供不同的生成方法,使用时,需要那种就让工厂类创建那种产品类。
public class Market{
public static Fruit createApple(){
return new Apple();
}
public static Fruit createOrange(){
return new Orange();
}
}
使用时:
Fruit apple = Market.createApple();
apple.desc();
Fruit orange = Market.createOrange();
orange.desc();
优点是需要那种就调用那种方法;
缺点是如果产品比较多,工厂类里面每个产品都需要一个方法创建。
3.抽象工厂:
以上介绍的工厂是单产品系,但抽象工厂是多产品系。
举个例子,超市有很多,每个超市的产品描述和价格都不一样。
//抽象超市类
public abstract class Market{
public abstract Fruit createFruit();
public abstract Vegetable createVegetable();
}
//抽象蔬菜类
public abstract class Vegetable{
public abstract void desc();
}
//具体蔬菜类
public class Cabbage extends Vegetable{
public void desc(){
System.out.print("小白菜");
}
}
public class Carrot extends Vegetable{
public void desc(){
System.out.print("白胡萝卜");
}
}
//具体超市类
public class JiaMarket extends Market{
@Override
public Fruit createFruit() {
return new Apple();//苹果
}
@Override
public Vegetable createVegetable() {
return new Carrot();//
}
}
public class HengMarket extends Market{
@Override
public Fruit createFruit() {
return new Orange();//
}
@Override
public Vegetable createVegetable() {
return new Cabbage ();//
}
}
使用:
Market market1 = new JiaMarket();
market1.createFruit().desc();
market1.createVegetable().desc();
Market market2 = new HengMarket();
market2.createFruit().desc();
market2.createVegetable().desc();
通过抽象工厂模式,模拟生活中的超市,你需要那个超市的产品,通过new那个超市类调用这个超市类的方法,得到你想要的。
Android中源码中的工厂方法模式实现
在android中,我们使用静态工厂方法的地方应该是创建Bitmap对象的时候。
Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
我们来看一下BitmapFactory的工厂方法具体实现
/**
* Synonym for {@link #decodeResource(Resources, int, android.graphics.BitmapFactory.Options)}
* will null Options.
*
* @param res The resources object containing the image data
* @param id The resource id of the image data
* @return The decoded bitmap, or null if the image could not be decode.
*/
public static Bitmap decodeResource(Resources res, int id) {
return decodeResource(res, id, null);
}
/**
* Synonym for opening the given resource and calling
* {@link #decodeResourceStream}.
*
* @param res The resources object containing the image data
* @param id The resource id of the image data
* @param opts null-ok; Options that control downsampling and whether the
* image should be completely decoded, or just is size returned.
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if opts is non-null, if opts requested only the
* size be returned (in opts.outWidth and opts.outHeight)
*/
public static Bitmap decodeResource(Resources res, int id, Options opts) {
Bitmap bm = null;
InputStream is = null;
try {
final TypedValue value = new TypedValue();
is = res.openRawResource(id, value);
bm = decodeResourceStream(res, value, is, null, opts);
} catch (Exception e) {
/* do nothing.
If the exception happened on open, bm will be null.
If it happened on close, bm is still valid.
*/
} finally {
try {
if (is != null) is.close();
} catch (IOException e) {
// Ignore
}
}
if (bm == null && opts != null && opts.inBitmap != null) {
throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
return bm;
}
通过静态工厂类的方法调用decodeResource(Resources res, int id),这方法最终调用decodeResource(res, id, null)方法返回itmap对象。