工厂方法模式

工厂方法模式定义
 定义一个用于创建对象的接口,让子类决定实例化那个类
工厂方法模式

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对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值