单例、多例模式&&工厂模式

单例、多例模式

假设,老张开车去东北

public class Car {
    public void run(){      
      System.out.println("冒着烟奔跑中car.........");
    }
}
public class Test {
    public static void main(String[] args) {    
        //如果把new交给司机,那么司机想new多少car就能有多少。
        Car c=new Car();
        c.run();        
    }
}

想要控制只给老张一辆车,不让他随便new出来,可以把Car的构造函数设为private,Car自主生产一个实例,不再依赖于new,封装一个方法,让Car定义一个方法返回唯一实例。

单例模式

public class Car {  
    private static Car car=new Car();   //实例
    private Car(){  }   //构造函数私有

    //单例模式的getInstance方法==静态工厂方法
    public static Car getInstance(){
       return car;  
    }   
    public void run(){
        System.out.println("冒着烟奔跑中car.........");
    }
}

测试:
因为Car的getInstance()方法返回static变量,是同一个实例,所以c1和c2是同一个对象。

public class Test { 
    public static void main(String[] args) {        
        Car c1=Car.getInstance();
        Car c2=Car.getInstance();
        if(c1==c2){
            System.out.print("same car");
        }       
    }
}

如果需要在Car中产生多个实例,不只是一个实例,可以用多例模式。
比如JDBC的连接池,从池中选择一条连接使用,使用后回收到池中,Connection就是多例

多例模式
在Car中定义List<Car>成员变量

private static List<Car> cars=new ArrayList<Car>();

再把cars初始化,当需要使用的时候,就从cars中选择一个使用。

工厂模式

new产生实例,如果想对对象的生产过程也能够进行定制,有好多可扩展性,且能封装生产过程,使用工厂模式

1、简单工厂模式

//Moveable接口用于实现run
public class Car implements Moveable{
    @Override
    public void run() {
        System.out.print("开汽车\n");
    }
} 
//Moveable接口用于实现run
public class Plane implements Moveable {
    @Override
    public void run() {
        System.out.print("开飞机\n");      
    }
}

工厂

public class CarFactory {
    public Car createCar(){
        return new Car();
    }
}
public class PlaneFactory {
    public Plane createPlane(){
        return new Plane();
    }
}
public class Test { 
    public static void main(String[] args) {
        PlaneFactory planeFactory=new PlaneFactory();
        Plane p=planeFactory.createPlane();//从工厂获取
        p.run();        
    }
}

简单工厂模式的工厂可扩展性不好,如果想要替换工厂,则换掉的工厂方法也得改,可扩展性不好

2、抽象工厂模式

产生交通工具的抽象工厂

public abstract class VehicleFactory {
    abstract Moveable create();
}

继承自抽象工厂类的具体工厂(子工厂)

public class CarFactory extends VehicleFactory{
    @Override
    Moveable create() {
        return new Car();
    }
}
public class PlaneFactory extends VehicleFactory{
    @Override
    Moveable create() {
        return new Plane();
    }
}
public class Test { 
    public static void main(String[] args) {
        VehicleFactory factory=new PlaneFactory();
        Plane p=(Plane) factory.create();//多态,会隐藏具体实现方法
        p.run();

        factory=new CarFactory();
        Car c=(Car) factory.create();//多态,会隐藏具体实现方法
        c.run();
    }
}

不仅可以控制对象,还可以控制对象的生产过程。
需要修改的只有VehicleFactory factory=new PlaneFactory();,需要生产什么对象,就new出相应的工厂,如果有配置文件,连这个都不用修改
这里写图片描述

体会:产生对象的方法,就是工厂方法,不一定局限于是在哪个位置,是哪个范畴,学习到最后要灵活运用,手中无剑心中有剑

getInstance和Factory在jdk中常用,还有abstractFactory也非常常用

3、配置文件

对于普通工厂来说,产生产品系列时,会产生工厂泛滥的问题,对于抽象工厂来说,也有一个问题:比如抽象工厂类,当它需要在抽象类中添加或者删去一个方法(即改变产品时),就需要改动所有继承自该厂的所有子类的方法,改动的地方太多
spring提供了一种方案:
1、spring提供的是bean工厂(BeanFactory)
2、原先通过new方式得到的实例Bean对象,现在通过配置文件的配置来配置实例

模拟spring
1、配置文件spring.properties

VehicleType=com.HL.spring.Train  //  键值对

2、通过java的Properties、反射来获取实例对象

package com.HL.spring;
import java.io.IOException;
import java.util.Properties;
public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {

        //用来读配置文件的
        Properties pros=new Properties();
        //Test.class.getClassLoader():拿到装载类对象的class装载器,getResourceAsStream:把文件当成流
        pros.load(Test.class.getClassLoader().getResourceAsStream("com/HL/spring/spring.properties"));

        //获取key为VehicleType的值
        String vehicleTypeName=pros.getProperty("VehicleType");
        System.out.println(vehicleTypeName);

        //运用java的反射机制,通过字符串得到实例
        Object o=Class.forName(vehicleTypeName).newInstance();
        Moveable m=(Moveable)o;
        m.run();    
    }
}

4、Spring

Spring中的运用:使用application.xml作为全局配置文件
application.xml中的配置信息

<Bean id="v" class="com.HL.spring.Car" />

加载配置文件,用ClassPathXmlApplication

BeanFactory f=new ClassPathXmlApplicationContext("application.xml");//加载配置文件中配置的Bean类

java解析XML文件,有多种方法,比如JDOM、SAX等,可以搜索一下JDOM/XPATH编程指南.
spring中加载完xml配置文件之后,会把配置文件中声明的Bean放在List中,然后放进Map中,即Bean容器(IOC),提供给应用程序(程序通过getBean根据id得到Bean),即AOP

Object o=f.getBean("v");//根据id获取相应ID的Bean实例
Moveable m=(Moveable)o;
m.run();

这就是Bean容器,即IOC。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值