Java设计模式之工厂系列(Factory)

工厂模式的简单介绍:为了降低程序的耦合性,增加程序的可扩展性和易维护性,提供的一种创建对象的方法。客户不需要直接new一个对象出来,可以直接去找相应的工厂来生产对象即可。这样,客户可以不去也不需要去了解创建对象的细节。而且,如果你是广泛采用new对象的方法,那你以后想修改对象的话,就需要找到所有的new。如果使用工厂的话,工厂的类型直接由配置文件来决定。需要修改类型时,你可以直接去修改配置文件,源代码甚至可以不用去修改。

工厂模式分为:
1.简单工厂(Simple Factory): 一个具体工厂,一个抽象产品,多个具体产品
2.工厂方法(Factory Method): 一个抽象工厂,多个具体工厂,一个抽象产品,多个具体产品
3.抽象工厂(Abstract Factory):一个抽象工厂,多个具体工厂,多个抽象产品,多个具体产品
4.介绍Spring中的BeanFactory使用和手动仿制一个Spring的bean工厂

简单工厂
目的:降低耦合,客户不需要知道产品的具体生产方式。
缺点:只有一个工厂,这个工厂任务繁重。

简单工厂的实例
汽车类

public class Car implements Vehicle{
    public void run(){
        System.out.println("突突突突....I'm car");
    }
}

飞机类

public class Plane implements Vehicle{
    public void run() {
        System.out.println("嗖嗖嗖嗖....I'm plane");
    }
}

工厂类

public class Factory {
    public Car getCar(){
        return new Car();
    }
    public Plane getPlane(){
        return new Plane();
    }
}

调用方法

public static void main(String[] args) {
        Factory f =new Factory();
        //拿到一辆车
        Vehicle vehicle=f.getCar();
        vehicle.run();
        //拿到一架飞机
        vehicle =f.getPlane();
        vehicle.run();
}

工厂方法
目的:在简单工厂的基础上,减少工厂的负担,将工厂个类型细化,抽象出一个总的工厂。
缺点:只能生产固定类型的产品,即只能生产交通工具。如果每辆交通工具上还要配备武器、吃的,那我们只能创建武器、吃的的工厂。这样,工厂发生了泛滥,而且结构混乱。
优点:达成了目的,可以在产品层上任意扩展(想提供创建轮船的服务,只需要添加Ship和ShipFactory类即可)。

工厂方法
Car、Plane、Vechile和简单工厂一样,不列出代码
VehicleFactory接口

public interface VehicleFactory {
    public Vehicle getVechicle();
}

汽车工厂

public class CarFactory implements VehicleFactory{
    public Vehicle getVechicle() {
        return new Car();
    }
}

飞机工厂

public class PlaneFactory implements VehicleFactory{
    public Vehicle getVechicle() {
        return new Plane();
    }
}

调用方法

public static void main(String[] args) {
    VehicleFactory factory =new CarFactory();
    factory.getVechicle().run();//生产出来的汽车run
    VehicleFactory f =new PlaneFactory();
    f.getVechicle().run();//生产出来的飞机run
}

抽象工厂
目的:解决工厂方法不能创建一系列产品的短板。
缺点:产品的扩展性差,只能生产固定系列的产品。
优点:实现了产品的系列化生产。

抽象工厂

AK47

public class AK47 implements Weapon{
    public void shoot() {
        System.out.println("哒哒哒嗒...I'm AK47");
    }
}

NutterTools

public class NutterTools implements Weapon{
    public void shoot() {
        System.out.println("批次咔哧...I'm NutterTools");
    }
}

GFSFactory

//高富帅的工厂
public class GFSFactory implements WeaponFactory,VehicleFactory{
    //高富帅坐飞机
    public Vehicle getVechicle() {
        return new Plane();
    }
    //高富帅保镖需要AK
    public Weapon getWeapon() {
        return new AK47();
    }

}

NutterFactory

//暴徒的工厂
public class NutterFactory implements VehicleFactory,WeaponFactory{
    //生产汽车
    public Vehicle getVechicle() {
        return new Car();
    }
    //生产暴徒武器
    public Weapon getWeapon() {
        return new NutterTools();
    }

}

================================================
什么是JavaBean?大致上可以这么理解:一种封装属性和方法来实现特殊功能的特殊对象。(加了复杂定语的对象)
JavaBean的结构很简单:
1.属性(私有):xxx
2.方法(公开):getXxx()、setXxx()
这种对象可以使用“内省”来操作它!

Spring提供了这种特殊对象的生产工厂的方法。这种工厂就是我们要介绍的BeanFactory。

看虾面的代码:

//还是我们上面定义的Vehicle接口
public interface Vehicle {
    void run();
}
//汽车类
public class Car implements Vehicle{
    public void run(){
        System.out.println("突突突突....I'm car");
    }
}

我们想使用Spring中的Bean工厂来生产汽车,就先把Spring的jar包全部导入进来(Spring的jar和logging的jar)。

Spring的BeanFactory使用前,为他配一个xml的配置文件

applicationContext.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- id相当于key、名字   class就是你类所在的完整目录 -->
    <!-- v=com.majin.BeanFactory.Car -->
    <bean id="v" class="com.majin.BeanFactory.Car">
    </bean>

</beans>

如下调用就可以的到你想要的对象了。

public static void main(String[] args) {
        BeanFactory factory =new ClassPathXmlApplicationContext("applicationContext.xml");
        Object o =factory.getBean("v");
        Vehicle v =(Vehicle)o;
        v.run();
}

这么做的好处大大的,你想啊,客户想修改一下程序,怎么修改?找配置文件啊。客户想扩展一下程序,怎么扩展?在你的应用文档中告诉客户实现那个接口,改一下配置文件啊。

================================================
觉得BeanFactory有点意思了吧。我们其实完全可以“自己动手,丰衣足食”,自己造一个和Spring的Bean工厂一样的工厂出来。(实际上,没必要自己去造)。

我们就需要自己去解析xml文件了,我采用的是dom4j来解析的(方法不唯一),导入dom4j的所有jar包

代码如下:

//在Spring中BeanFactory就是一个接口,我们做一个相同的接口
public interface BeanFactory {
    public Object getBean(String id);
}
//定义实现BeanFactory的类(照猫画虎)
public class ClassPathXmlApplicationContext implements BeanFactory {

    // the container of object
    Map<String, Object> container = new HashMap<String, Object>();

    /**
     * constructor of ClassPathXmlApplicationContext
     * @param path
     *            the position of the xml
     * @throws Exception
     *             class not found
     */
    public ClassPathXmlApplicationContext(String fileName)
            throws InstantiationException, IllegalAccessException, Exception {
        //根据fileName解析xml,把里面所有的<bean>中的id、class解析出来,存到我们的容器中。
        SAXReader reader = new SAXReader();
        Document document = reader.read(filename);
        Element root = document.getRootElement();
        Iterator it =root.elementIterator("bean");
        while (it.hasNext()) {
            Element e = (Element) it.next();
            String id = e.attributeValue("id");
            String clazz = e.attributeValue("class");

            // create the instance of the clazz
            Object o = Class.forName(clazz).newInstance();
            container.put(id, o);
        }
    }

    @Override
    public Object getBean(String id) {
        return container.get(id);
    }
}
//同样的调用,同样的结果
public static void main(String[] args) throws Exception {
        BeanFactory factory =new ClassPathXmlApplicationContext("xml/applicationContext.xml");
        Object o = factory.getBean("v");
        Vehicle v = (Vehicle)o;
        v.run();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值