OO之工厂模式

以下为工厂模式的详解,包括简单工厂,普通工厂模式,抽象工厂。

引子:

       假设有一个交通工具公司,生产自行车,汽车,飞机等,现要销售该公司的产品,要怎么设计呢?

       在交通工具商店中加一个if else判断如果是自行车就实例化(new)一个自行车,如果是汽车就实例化(new)一个汽车吗,当然不是,这样的话如果将来又加了多种交通工具那要更改每一个商店的代码,这样的话更改太多,我们应该把这部分可能变更的代码封装到另一个对象中,这个对象只管生产何种交通工具,要获得交通工具就用它。

简单工厂:

类图:

设计:

/**
 * 抽像的交通工具类,里面有生产交通工具的过程方法(控制生产过程)
 * @author Homg
 *
 */
public abstract class Vehicle {
        public abstract void produceComponent();
        public abstract void assemble();
        public abstract void test();
}

 

具体产品类,其他具体产品类(bike,plane)省略,完整代码在文章的最下方有下载地址:

/**
 * 具体的产品,继承自抽象类,以用被工厂生产出来
 * @author Homg
 *
 */
public class Car extends Vehicle{

    @Override
    public void produceComponent() {
        // TODO Auto-generated method stub
        System.out.println("生产汽车零件");
    }

    @Override
    public void assemble() {
        // TODO Auto-generated method stub
        System.out.println("组装成汽车");
    }

    @Override
    public void test() {
        // TODO Auto-generated method stub
        System.out.println("测试汽车性能");
    }

}
/**
 * 简单交通工具工厂,这是唯一new具体交通工具的地方
 * 
 * @author Homg
 * 
 */
public class SimpleVehicleFactory {
    // 该方法也可以是静态的(静态工厂)
    public Vehicle createVehicle(String type) {
        Vehicle vehicle = null;
        if ("bike".equals(type)) {
            vehicle = new Bike();
        } else if ("car".equals(type)) {
            vehicle = new Car();
        } else if ("plane".equals(type)) {
            vehicle = new Plane();
        }
        //可以设置默认产品以免为null
        return vehicle;
    }
}
/**
 * 销售交通工具,工厂的使用者。
 * 
 * @author Homg
 * 
 */
public class VehicleStore {
    // 工厂的引用,从构造函数中获得
    private SimpleVehicleFactory factory;

    public VehicleStore(SimpleVehicleFactory factory) {
        this.factory = factory;
    }

    // 通过传入订单的类型来获得相应的产品,不需要实例化(new)任何一个具体类,全部通过createVehicle()来获得。
    public Vehicle orderVehicle(String type) {
        Vehicle vehicle;
        vehicle = factory.createVehicle(type);
        vehicle.produceComponent();
        vehicle.assemble();
        vehicle.test();
        return vehicle;
    }
}

测试:

    public static void main(String[] args) {
        SimpleVehicleFactory factory = new SimpleVehicleFactory();
        VehicleStore vehicleStore = new VehicleStore(factory);
        // 依次生产三种交通工具
        Vehicle vehicle1 = vehicleStore.orderVehicle("car");
        System.out.println("-------------------------------------");
        Vehicle vehicle2 = vehicleStore.orderVehicle("bike");
        System.out.println("-------------------------------------");
        Vehicle vehicle3 = vehicleStore.orderVehicle("plane");
    }

运行结果:
生产汽车零件
组装成汽车
测试汽车性能
-------------------------------------
生产自行车零件
组装成自行车
测试自行车性能
-------------------------------------
生产飞机零件
组装成飞机
测试飞机性能

˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙

      以后如果有新的交通工具要生产,只需要更改工厂类一处即可,商店类中不需要实例化任何一个具体的交通工具类,实例化(new)操作都放到工厂类的方法中。工厂类中的创建方法也可以改成静态的(静态工厂),这样可以不用实例化对象来使用工厂方法。

     简单工厂严格来说并不是真正的工厂模式,下来我们来看普通工厂模式

     现在该公司不仅要在中国销售产品,还要把产品销售到俄罗斯,也就是说,不仅要分多种产品类型,还要分不同区域生产不同风格的产品。

先看一下工厂模式的基本类图:

设计(省略部分类似代码,完整代码在文章的最下方有下载地址。):

     首先要进行一些质量控制,确保分公司产品是用的总公司的流程,但不同地区的产品又需要有自己的变化,所以产品类应该这样:

 

/**
 * 产品类,抽像的交通工具类,里面有生产交通工具的过程方法(控制生产过程),但抽象的由子具体实现
 * 
 * @author Homg
 * 
 */
public abstract class Vehicle {
    String name;
    //各种零件
    String tyre;
    String engine;
    String body;

    public void produceComponent() {
        System.out.println("名字:" + name);
        System.out.println("轮胎:" + tyre);
        System.out.println("引擎:" + engine);
        System.out.println("机身:" + body);
    }

    public abstract void assemble();

    public abstract void test();
}

 

子类决定具体的产品(其他具体产品类省略):

 

/**
 * 具体的产品,继承自抽象类,根据不同地域有不同的产品
 * @author Homg
 *
 */
public class ChineseCar extends Vehicle{
    
    public ChineseCar() {
        name="中国汽车";
        tyre="中国汽车轮胎";
        engine="中国汽车引擎";
        body="中国风格汽车机身";
    }

    @Override
    public void assemble() {
        // TODO Auto-generated method stub
        System.out.println("组装成中国风格汽车");
    }

    @Override
    public void test() {
        // TODO Auto-generated method stub
        System.out.println("测试俄中国格汽车性能");
    }

}

 

/**
 * 具体的产品,继承自抽象类,根据不同地域有不同的产品
 * @author Homg
 *
 */
public class RussiaCar extends Vehicle{
    
    public RussiaCar() {
        name="俄罗斯汽车";
        tyre="俄罗斯汽车轮胎";
        engine="俄罗斯汽车引擎";
        body="俄罗斯风格汽车机身";
    }

    @Override
    public void assemble() {
        // TODO Auto-generated method stub
        System.out.println("组装成俄罗斯风格汽车");
    }

    @Override
    public void test() {
        // TODO Auto-generated method stub
        System.out.println("测试俄罗斯风格汽车性能");
    }

}

 

工厂类需要制定一个框架,既要生产产品,不同区域又可以生产不同的产品(抽象的工厂方法):

 

/**
 * 创建者类,定义了一个抽象的工厂方法,由子类具体实现创建什么新产品
 * @author Homg
 *
 */
public abstract class VehicleFactory {
    //生产产品,不用管具体生产什么产品,由createVehicle方法来管
    public Vehicle orderVehicle(String type) {
        Vehicle vehicle;
        vehicle = createVehicle(type);
        vehicle.produceComponent();
        vehicle.assemble();
        vehicle.test();
        return vehicle;
    }
    //抽象的创建产品方法,返回具体的产品,参数决定是什么产品。
    protected abstract Vehicle createVehicle(String type);
    //其他方法
}

 

子类工厂重写工厂方法,决定生产什么地区的产品:

 

/**
 * 具体的工厂类,根据不同地域创建不同的产品
 * 
 * @author Homg
 * 
 */
public class ChineseVehicleFactory extends VehicleFactory {
    // 创建不同的产品
    @Override
    protected Vehicle createVehicle(String type) {
        // TODO Auto-generated method stub
        Vehicle vehicle = null;
        if ("bike".equals(type)) {
            vehicle = new ChineseBike();
        } else if ("car".equals(type)) {
            vehicle = new ChineseCar();
        }
        // 可以设置默认产品以免为null
        return vehicle;
    }

}

 

/**
 * 具体的工厂类,根据不同地域创建不同的产品
 * 
 * @author Homg
 * 
 */
public class RussiaVehicleFactory extends VehicleFactory {
    // 创建不同的产品
    @Override
    protected Vehicle createVehicle(String type) {
        // TODO Auto-generated method stub
        Vehicle vehicle = null;
        if ("bike".equals(type)) {
            vehicle = new RussiaBike();
        } else if ("car".equals(type)) {
            vehicle = new RussiaCar();
        }
        // 可以设置默认产品以免为null
        return vehicle;
    }

}

测试:

 

    public static void main(String[] args) {
        VehicleFactory chinesefactory=new ChineseVehicleFactory();
        Vehicle chineseVehicle1=chinesefactory.orderVehicle("bike");
        System.out.println("--------------------------------------");
        Vehicle chineseVehicle2=chinesefactory.orderVehicle("car");
        System.out.println("--------------------------------------");
        VehicleFactory russiaFactory=new RussiaVehicleFactory();
        russiaFactory.orderVehicle("bike");
        System.out.println("--------------------------------------");
        russiaFactory.orderVehicle("car");
    }

运行结果:

名字:中国自行车
轮胎:中国自行车轮胎
引擎:生物动力
机身:中国风格自行车机身
组装成中国风格自行车
测试中国风格自行车性能
--------------------------------------
名字:中国汽车
轮胎:中国汽车轮胎
引擎:中国汽车引擎
机身:中国风格汽车机身
组装成中国风格汽车
测试俄中国格汽车性能
--------------------------------------
名字:俄罗斯自行车
轮胎:俄罗斯自行车轮胎
引擎:生物动力
机身:俄罗斯风格自行车机身
组装成俄罗斯风格自行车
测试俄罗斯风格自行车性能
--------------------------------------
名字:俄罗斯汽车
轮胎:俄罗斯汽车轮胎
引擎:俄罗斯汽车引擎
机身:俄罗斯风格汽车机身
组装成俄罗斯风格汽车
测试俄罗斯风格汽车性能

类图(产品和工厂是平行的类层级):

理解:

  工厂方法可以封装实例化的行为,封装以后可能经常变化的代码,避免代码的重复,方便以后维护。

˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙˙☆`·.·˙˙`·..·˙˙`·..·˙☆`·.·˙˙`·..·˙☆˙

      现在来谈谈零件的生产,每次该公司要生产一批零件,用以制造某个产品,这时可以看看抽象工厂

基本类图如下:

 

设计:

抽象工厂类:

 

/**
 * 抽象工厂接口,定义了一组接口用来创建产品
 * @author Homg
 *
 */
public interface ComponentFactory {
        public Tyre createTyre();
        public Engine createEngine();
        public Body createBody();
}

 

具体工厂类,不同地区的零件有不同的具体工厂:

/**
 * 具体工厂,实现了产品家族,用户想要什么产品就用什么工厂,不需要实例化任何产品
 * @author Homg
 *
 */
public class ChineseComponentFactory implements ComponentFactory {

    @Override
    public Tyre createTyre() {
        // TODO Auto-generated method stub
        return new ChineseTyre();
    }

    @Override
    public Engine createEngine() {
        // TODO Auto-generated method stub
        return new ChineseEngine();
    }

    @Override
    public Body createBody() {
        // TODO Auto-generated method stub
        return new ChineseBody();
    }

}
/**
 * 具体工厂,实现了产品家族,用户想要什么产品就用什么工厂,不需要实例化任何产品
 * @author Homg
 *
 */
public class RussiaComponentFactory implements ComponentFactory {

    @Override
    public Tyre createTyre() {
        // TODO Auto-generated method stub
        return new RussiaTyre();
    }

    @Override
    public Engine createEngine() {
        // TODO Auto-generated method stub
        return new RussiaEngine();
    }

    @Override
    public Body createBody() {
        // TODO Auto-generated method stub
        return new RussiaBody();
    }

}

零件家族(省略其他零件类:engine,body。完整代码在文章的最下方有下载地址):

 

/**
 * 抽象产品
 * @author Homg
 *
 */
public abstract class Tyre {
    String name;

    public String getName() {
        return name;
    }
    
}

 

/**
 * 具体产品
 * @author Homg
 *
 */
public class RussiaTyre extends Tyre {

    public RussiaTyre() {
        name="俄罗斯轮胎";
    }

}

 

/**
 * 具体产品
 * @author Homg
 *
 */
public class ChineseTyre extends Tyre {

    public ChineseTyre() {
        name = "中国轮胎";
    }

}

客户类:

 

/**
 * 客户类
 * @author Homg
 *
 */
public class Client {
    private Tyre tyre;
    private Engine engine;
    private Body body;
    private ComponentFactory componentFactory;

    public Client(String zoom) {
        if ("俄罗斯".equals(zoom)) {
            componentFactory = new RussiaComponentFactory();
            tyre = componentFactory.createTyre();
            engine = componentFactory.createEngine();
            body = componentFactory.createBody();
            System.out.println("生产的一批零件为:" + tyre.getName() + ","
                    + engine.getName() + "," + body.getName());
        } else if ("中国".equals(zoom)) {
            componentFactory = new ChineseComponentFactory();
            tyre = componentFactory.createTyre();
            engine = componentFactory.createEngine();
            body = componentFactory.createBody();
            System.out.println("生产的一批零件为:" + tyre.getName() + ","
                    + engine.getName() + "," + body.getName());
        }
    }
}

 

 测试:

    public static void main(String[] args) {
        Client client1=new Client("俄罗斯");
        System.out.println("------------------------------");
        Client client2=new Client("中国");
    }

运行结果:
生产的一批零件为:俄罗斯轮胎,俄罗斯引擎,俄罗斯机身
------------------------------
生产的一批零件为:中国轮胎,中国引擎,中国机身

理解:

  由上面可以看出,抽象工厂是用来创建一组产品的,也就是产品家族,用户不需要关心实际生产的具体产品是什么,只需要使用相应的工厂,这样可以将用户从具体产品中解耦。

      而普通工厂可以理解为是用来生产一个产品,抽象工厂用来生产产品家族。

总结:

  普通工厂模式:定义了一个创建产品对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

  抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

完整代码下载地址(也可以留下邮箱发给你):

 http://download.csdn.net/detail/homg92/6919563

 

posted @ 2014-02-13 15:50  竹尘居士  阅读(1661)  评论(4编辑  收藏  举报