java设计模式之工厂系列

来源:互联网 发布:effective java第2版 编辑:程序博客网 时间:2024/05/21 08:56

工厂模式

在讲工厂模式之前先了解下单例模式

单例模式的要点
  显然单例模式的要点有三个;一是某各类只能有一个实例;二是它必须自行创建这个事例;三是它必须自行向整个系统提供这个实例。在下面的对象图中,有一个"单例对象",而"客户甲""客户乙"客户丙"是单例对象的三个客户对象。可以看到,所有的客户对象共享一个单例对象。而且从单例对象到自身的连接线可以看出,单例对象持有对自己的引用。

下面给出把Car设计成单例模式的代码:

public class Car {public Car(){}private static Car car = new Car();public static Car getInstance() {return car;}public void run() {System.out.println("冒着烟奔跑中car.......");}}

这样就只有Car自己才能创建一个Car类,如果为一个司机提供一个Car代码如下:

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

以上是单例,如果在Car类中加入如下语句:

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

这样在调用getInstance时可以返回cars里面的任意一个Car,这种叫做多例,一个实例就是JDBC中的连接池。下面来看看简单工厂,如果我们想要控制它的生产过程首先我们要抽象出来一个接口Moveable代码如下:

public interface Moveable {void run();}

CarPlaneBroom去实现这个接口代码如下:

public class Broom implements Moveable {public void run() {System.out.println("一路沙尘暴飞奔而来broom.....");}}public class Plane implements Moveable {public void run() {System.out.println("扇着翅膀前进中plane....");}}public class Car implements Moveable {public void run() {System.out.println("冒着烟奔跑中car.......");}}

然后抽象出来一个VehicleFactory用来控制生产过程代码如下:

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

这样PlaneFactory,CarFactory,BroomFactory就可以来继承了,从而实现多态,代码如下:

public class BroomFactory extends VehicleFactory{public Moveable create() {return new Broom();}}public class CarFactory extends VehicleFactory{public Moveable create() {return new Car();}} public class PlaneFactory extends VehicleFactory{public Moveable create() {return new Plane();}}

测试的代码就是下面这样的:

public class Test {public static void main(String[] args) {//Car c = Car.getInstance();//Car c2 = Car.getInstance();VehicleFactory factory = new BroomFactory();Moveable m = factory.create();//if(c == c2) System.out.println("same car");m.run();}}

这样要生产出不同的东西只需要new出不同的工厂就可以了。如下图所示:


下面介绍抽象工厂,是如果想换掉一系列产品,就是用抽象工厂。

首先抽象出Vehicle,代码如下:

public abstract class Vehicle {public abstract void run();}

然后CarVehicle继承代码如下:

public class Car extends Vehicle {public void run() {System.out.println("冒着烟奔跑中car.......");}}

然后BroomVehicle继承代码如下:

public class Broom  extends Vehicle{public void run() {System.out.println("一路沙尘暴飞奔而来broom.....");}}

然后抽象出Food代码如下:

public abstract class Food {public abstract void printName();}

AppleFood继承代码如下:

public class Apple extends Food {public void printName() {System.out.println("apple");}}

MushRoomFood继承代码如下:

 public class MushRoom extends Food {@Overridepublic void printName() {// TODO Auto-generated method stubSystem.out.println("mushroom");}}

然后抽象出Weapon代码如下:

public abstract class Weapon {public abstract void shoot();}

AK47Weapon继承代码如下:

public class AK47 extends Weapon{public void shoot() {System.out.println("哒哒哒...");}}

MagicStickWeapon继承代码如下:

public class MagicStick extends Weapon {@Overridepublic void shoot() {System.out.println("fire hu hu hu ...");}}

然后抽象出来一个AbstractFactory代码如下:

public abstract class AbstractFactory {public abstract Vehicle createVehicle();public abstract Weapon createWeapon();public abstract Food createFood();}

在它里面有一些抽象方法用来产生VehicleWeaponFood,而对于具体产生什么要看继承他的具体类的实现MagicFactory 代码如下:

public class MagicFactory extends AbstractFactory {@Overridepublic Food createFood() {// TODO Auto-generated method stubreturn new MushRoom();}@Overridepublic Vehicle createVehicle() {// TODO Auto-generated method stubreturn new Broom();}@Overridepublic Weapon createWeapon() {// TODO Auto-generated method stubreturn new MagicStick();}}

DefaultFactory代码如下:

public class DefaultFactory extends AbstractFactory{@Overridepublic Food createFood() {// TODO Auto-generated method stubreturn new Apple();}@Overridepublic Vehicle createVehicle() {// TODO Auto-generated method stubreturn new Car();}@Overridepublic Weapon createWeapon() {// TODO Auto-generated method stubreturn new AK47();}}

测试类的代码如下:

public class Test {public static void main(String[] args) {//DefaultFactory f = new DefaultFactory();AbstractFactory f = new DefaultFactory();Vehicle v = f.createVehicle();v.run();Weapon w = f.createWeapon();w.shoot();Food a = f.createFood();a.printName();}}

这样当我想要整体更换时只需要new 出新的Factory就行了,这就是抽象工厂。它的一个实例如界面换皮肤,皮肤换了按钮,菜单都跟着换了。

总结简单工厂的缺点是容易造成工厂泛滥,而抽象工厂的缺点是在产生产品系列的时候要改动的地方太多。

下面介绍在配置文件中来指定所要new的对象,sping.properties配置文件如下:

VehicleType=com.bjsxt.spring.factory.Car

Test代码如下:

public class Test {/** * @param args * @throws IOException  */public static void main(String[] args) throws Exception {Properties props = new Properties();props.load(Test.class.getClassLoader().getResourceAsStream("com/bjsxt/spring/factory/spring.properties"));String vehicleTypeName = props.getProperty("VehicleType");Object o = Class.forName(vehicleTypeName).newInstance();Moveable m = (Moveable)o;m.run();}}

上面首先从配置文件中读出vehicleTypeName然后利用反射来取得这个对象。

下面用spring来代替上面的,首先建立一个配置文件applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?><beans>  <bean id="v" class="com.bjsxt.spring.factory.Train">  </bean>    <!--  //v=com.bjsxt.spring.factory.Car  --></beans>

然后在Test中只需要这样写就可以了:

public class Test {/** * @param args * @throws IOException  */public static void main(String[] args) throws Exception {BeanFactory f = new ClassPathXmlApplicationContext("com/bjsxt/spring/factory/applicationContext.xml");Object o = f.getBean("v");Moveable m = (Moveable)o;m.run();}}

当然要注意加入spring的相应的jar包。

























 

原创粉丝点击