2、问题的引出
a) 上面要么只生产一个Car、要么只生产一个Plane、那如果我要描述一个开着车、拿着AK47、边吃苹果的怎么弄?可以制定一系列产品。
b) 简单。既然使用工厂、那么就让一个工厂为我们创建一系列的产品――DefaultFactory代码:
package com.chy.dp.factory.abstractfactory;
public class DefaultFactory{
public Food createFood() {
return new Apple();
}
public Vehicle createVehicle() {
return new Car();
}
public Weapon createWeapon() {
return new AK47();
}
}
c) 生产的具体的东西也要有一个抽象类作为其父类来统一指定――Food代码:Apple代码:
package com.chy.dp.factory.abstractfactory;
public abstract class Food {
public abstract void printName();
}
package com.chy.dp.factory.abstractfactory;
public class Apple extends Food {
public void printName() {
System.out.println("apple....");
}
}
d) 其他几个JavaBean也是非常相似的定义。不再一一列出。
e) 当我们想换另一系列的产品的时候、比如想让工厂给我生产一套魔法扫帚、魔法棒、毒蘑菇、就创建另一个工厂来生产另一系列的产品――MagicFactory代码:
package com.chy.dp.factory.abstractfactory;
public class MagicFactory {
public Food createFood() {
return new MushRoom();
}
public Vehicle createVehicle() {
return new Broom();
}
public Weapon createWeapon() {
return new MagicStick();
}
}
f) 那么我们要使用第二个工厂的时候就要丢弃DefaultFactory、来从新new一个MagicFactory、下面的代码也要跟着变。关键是我不想改变下面的方法怎么办?
3、问题的解决过程
很随意的想到抽象出其父类或者接口、这也是我们常说的面下个接口编程。
a) 为我们所有的工厂类抽象出来一个抽象工厂、并且这个工厂的生产方式不能写死、应由子类去具体实现、所以方法的返回值也是生产产品的抽象类或者接口――AbstractFactory代码:
package com.chy.dp.factory.abstractfactory;
/**
* 根据具体的工厂产生具体的产品
* @author Administrator
*
*/
public abstract class AbstractFactory {
public abstract Vehicle createVehicle();
public abstract Weapon createWeapon();
public abstract Food createFood();
}
b) 那么我们所有的工厂都要从AbstractFactory来继承、并且实现自己特有的生产方式――DefaultFactory代码:MagicFactory代码:
package com.chy.dp.factory.abstractfactory;
public class DefaultFactory extends AbstractFactory{
@Override
public Food createFood() {
return new Apple();
}
@Override
public Vehicle createVehicle() {
return new Car();
}
@Override
public Weapon createWeapon() {
return new AK47();
}
}
package com.chy.dp.factory.abstractfactory;
public class MagicFactory extends AbstractFactory{
@Override
public Food createFood() {
return new MushRoom();
}
@Override
public Vehicle createVehicle() {
return new Broom();
}
@Override
public Weapon createWeapon() {
return new MagicStick();
}
}
c) 上面的工厂生产的东西都是返回的他们的共同的父类的类型、这样的目的是可以动态的指向生产的实例、所以具体的产品类也需要一个抽象的父类或者接口来统一指向他们的具体的实例的索引。这样在调用工厂的时候就可以用他们共同的父类来接收。、
d) Client:
package com.chy.dp.factory.abstractfactory;
public class Client {
public static void main(String[] args) {
//DefaultFactory f = new DefaultFactory();
AbstractFactory f = new DefaultFactory();
Vehicle c = f.createVehicle();
c.run();
Weapon ak = f.createWeapon();
ak.shoot();
Food a = f.createFood();
a.printName();
}
}
五:简单工厂与抽象工厂的比较
简单工厂可以在产品的纬度上进行扩展、即可以添加一个或者多个新的产品、但是要添加一系列产品则会非常困难、并且每添加一个产品就要添加一个工厂、那一个系列会有多少个产品呢?这样工厂会越来越多、这样就产生了一个现象――工厂泛滥!
抽象工厂可以一次添加一个系列、但是能产生一个新的产品品种吗?会非常麻烦!因为你要动最上层的抽象工厂、并且还要为所有实现了他的具体个工厂提供实现!如果你工厂多的话、比方说有几万个!会不会不敢想想?没有完美的解决方案、一方面多了、另一方面就必然要做出让步。
六:模拟spring的bean工厂
这里模拟的当然不可能是spring的BeanFacotry的所有功能、而是仅仅模拟他的一个子类:ClassPathXmlApplicationContext这个类、用来解析spring的配置文