Java设计模式笔记之工厂模式

1.前言

简单工厂模式、工厂模式、抽象工厂模式......这三个模式有没有把你搞晕?我反正是晕了。不过,再晕也要弄清楚啊!

话不多说回到正题,学习工厂方法模式。

工厂方法模式,是创建型设计模式之一。是一种结构简单的模式,实际开发中我们其实经常使用该模式,比如Android中的Activity里的生命周期方法。

2.定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

3.UML类图



Product:抽象产品类

Factory:抽象工厂类

ConcreteProduct:具体产品类

ConcreteFactory:具体工厂类

4.简单实现

下面是一个工厂方法模式的通用模式代码

//抽象产品类
public abstract class Product {
    /**
     * 产品类的抽象方法
     * 由具体的产品类去实现
     *
     */
    public abstract void method();


}

/**
 * Created by zsf.
 * 具体产品类A
 */

public class ConcreteProductA extends Product {


    @Override
    public void method() {
        Log.d("zsf","我是具体的产品A");
    }
}

/**
 * Created by zsf .
 * 具体产品类B
 */

public class ConcreteProductB extends Product {

    @Override
    public void method() {
        Log.d("zsf","我是具体的产品B");
    }
}

/**
 * Created by zsf.
 * 抽象工厂类
 */

public abstract class Factory {

    /**
     * 抽象工厂方法
     * 具体生产什么由子类去实现
     *
     * @return 具体的产品对象
     */

    public abstract Product createProduct();
}


/**
 * Created by zsf.
 * 具体工厂类
 */

public class ConcreteFactory extends Factory {
    @Override
    public Product createProduct() {

        return new ConcreteProductA();
    }
}

//客户端类
public class FactoryPatternTestActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Factory factory = new ConcreteFactory();
        Product p = factory.createProduct();
        p.method();
    }
}

打印出Log

03-31 22:08:04.694 6187-6187/? D/zsf: 我是具体的产品A

以上就是一个通用模式的组成。

  1. 抽象工厂,工厂方法模式的核心
  2. 具体工厂,实现具体业务逻辑
  3. 抽象产品,工厂方法模式所创建的产品的父类
  4. 具体产品,实现抽象产品的某个具体产品的对象

上面的代码还可以优化,我们在客户端想要得到具体产品B的实例,就需要在具体工厂类中修改返回的return,将其改为

return new ConcreteProductB();

这里就像我是一个机械厂的老板,我手下机械厂只有一条生产线,往常都是在生产A类产品,突然我接了个B类的大订单。我就通知下去,这条线改为生产B类产品。总结起来就是:我需要哪种产品就生产哪种产品。

代码修改的地方虽然不多,但是作为追求高水准的工程师,我们还可以试用更好的方式来决定生产哪种产品——反射

我们在抽象工厂类中,修改工厂方法createProduct()

public abstract class Factory {

    /**
     * 抽象工厂方法
     * 具体生产什么由子类去实现
     *
     * @return 具体的产品对象
     */

    public abstract<T extends Product> T createProduct(Class<T> tClass);
}

修改具体的工厂类,通过反射获取类的实例:

/**
 * Created by zsf.
 * 具体工厂类
 */

public class ConcreteFactory extends Factory {


    @Override
    public <T extends Product> T createProduct(Class<T> tClass) {
        Product p = null;
        try {
            p = (Product) Class.forName(tClass.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) p;
    }
}

最后,客户端代码:

public class FactoryPatternTestActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Factory factory = new ConcreteFactory();
        Product p = factory.createProduct(ConcreteProductB.class);
        p.method();
    }
}

这样的话,直接在客户端修改就好了。

也有直接为每一个产品去定义一个具体的工厂类的,ConcreteProductA、ConcteteProductB,然后分别在客户端是实现。这样的方法称为多工厂方法模式。当你确定你的工厂只会有一个的时候就可以继续简化你的代码,不再使用抽象工厂,而是将对应的工厂方法改为静态即可。

public class Factory {

    public static Product createProduct(){
        
        return new ConcreteProductA();
    }
}

上面的这种工厂模式其实就是简单工厂模式

完整简单例子代码如下,生产三种材质齿轮的工厂方法模式实现。

/**
 * Created by zsf.
 * 抽象机械工厂类
 */

public abstract class MechanicalFactory {

    //某齿轮的工厂方法
    public abstract <T extends Gear> T createGear(Class<T> tClass);


}

/**
 * Created by zsf.
 * 生产三种不同材质的齿轮,大小相同,(假设)直接使用一条生产线
 */

public class GearFactory extends MechanicalFactory {
    @Override
    public <T extends Gear> T createGear(Class<T> tClass) {
        Gear gear = null;
        try {
            gear = (Gear) Class.forName(tClass.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) gear;
    }
}

/**
 * Created by zsf
 * 抽象产品类——齿轮
 */

public abstract class Gear {

    //不同材质的齿轮
    public abstract void material();

    //齿数
    public abstract void numberOfTeeth();
}

/**
 * Created by zsf.
 * 铸钢齿轮
 */

public class CastSteelGear extends Gear {
    @Override
    public void material() {
        Log.d("zsf","我是铸钢材质齿轮");
    }

    @Override
    public void numberOfTeeth() {
        Log.d("zsf","我的齿数为20");
    }
}

/**
 * Created by zsf.
 * 铸铁材质齿轮
 */

public class CastIronGear extends Gear {
    @Override
    public void material() {
        Log.d("zsf","我是铸铁材质齿轮");
    }

    @Override
    public void numberOfTeeth() {
        Log.d("zsf","我的齿数为22");
    }
}

/**
 * Created by zsf.
 */

public class ForgedSteelGear extends Gear {
    @Override
    public void material() {
        Log.d("zsf","我是锻钢材质齿轮");
    }

    @Override
    public void numberOfTeeth() {
        Log.d("zsf","我的齿数为25");
    }
}

客户端代码:

/**
 * Created by zsf
 */

public class ProductGearTestActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //1.构造一个生产齿轮的工厂对象
        MechanicalFactory factory = new GearFactory();

        //2.1生产锻钢齿轮
        ForgedSteelGear forgedSteelGear = factory.createGear(ForgedSteelGear.class);
        forgedSteelGear.material();
        forgedSteelGear.numberOfTeeth();

        //2.2生产铸钢齿轮
        CastSteelGear castSteelGear = factory.createGear(CastSteelGear.class);
        castSteelGear.material();
        castSteelGear.numberOfTeeth();

        //2.3生产铸铁齿轮
        CastIronGear castIronGear = factory.createGear(CastIronGear.class);
        castIronGear.material();
        castIronGear.numberOfTeeth();

    }
}

打印Log

03-31 23:29:55.212 18942-18942/? D/zsf: 我是锻钢材质齿轮
03-31 23:29:55.212 18942-18942/? D/zsf: 我的齿数为25
03-31 23:29:55.212 18942-18942/? D/zsf: 我是铸钢材质齿轮
03-31 23:29:55.212 18942-18942/? D/zsf: 我的齿数为20
03-31 23:29:55.212 18942-18942/? D/zsf: 我是铸铁材质齿轮
03-31 23:29:55.212 18942-18942/? D/zsf: 我的齿数为22







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值