设计模式——工厂模式
一、简 介
工厂设计模式主要是为创建对象提供过度接口,以便将创建对象的具体过程封装起来,达到提高灵活性的目的
工厂模式在《Java与模式》中分为三类:
1) 简单工厂模式(Simple Factory)
2) 工厂方法模式(Factory Method)
3) 抽象工厂模式(Abstract Factory)
二、简单工厂模式
1) 抽象产品角色:具体产品角色对应的类所要继承或实现的抽象类或接口
2) 具体产品角色:工厂类所要创建的对象就是此类的实例,是一个具体类来实现
3) 具体工厂角色:该模式的核心,具有一定的商业逻辑与判断逻辑,是一个具体类来实现
简单代码实现如下:
- interface Fruit {
- public void eat();
- }
- class Apple implements Fruit {
- @Override
- public void eat(){
- System.out.println("Eat Apple!");
- }
- }
- class Orange implements Fruit {
- @Override
- public void eat(){
- System.out.println("Eat Orange!");
- }
- }
- class Factory {
- public static Fruit getInstance(String className){
- Fruit f = null;
- if ("Apple".equalsIgnoreCase(className)){
- f = new Apple();
- }
- else if ("Orange".equalsIgnoreCase(className)){
- f = new Orange();
- }
- else{
- //to add
- }
- return f;
- }
- }
- public class FactoryDemo {
- public static void main(String[] args) {
- Fruit f = Factory.getInstance("apple");//getInstance(args[0])中的参数可以用户输入
- f.eat();
- }
- }
以上代码中,如果有新的水果加入,只需要更改Factory类中的判断逻辑条件即可,不用去改动main方法(该方法对应客户端)。
三、工厂方法模式
1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类,在Java中它由抽象类或者接口来实现。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口,在Java中一般有抽象类或者接口来实现。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例,在Java中由具体的类来实现。
简单代码实现如下:
- //抽象产品角色
- interface Moveable {
- void run();
- }
- //具体产品角色
- class Plane implements Moveable {
- @Override
- public void run() {
- System.out.println("plane running...");
- }
- }
- class Train implements Moveable {
- @Override
- public void run() {
- System.out.println("train running...");
- }
- }
- //抽象工厂
- abstract class VehicleFactory {
- abstract Moveable create();
- }
- //具体工厂
- class PlaneFactory extends VehicleFactory{
- public Moveable create() {
- return new Plane();
- }
- }
- class TrainFactory extends VehicleFactory{
- public Moveable create() {
- return new Train();
- }
- }
- //测试类
- public class FactoryDemo {
- public static void main(String[] args) {
- VehicleFactory factory = new TrainFactory();
- Moveable m = factory.create();
- m.run();
- }
- }
四、抽象工厂模式
示例代码如下:
- //抽象产品类
- abstract class Vehicle {
- public abstract void run();
- }
- abstract class Weapon {
- public abstract void shoot();
- }
- abstract class Food {
- public abstract void eat();
- }
- //具体产品类
- class Car extends Vehicle {
- public void run(){
- System.out.println("car running...");
- }
- }
- class Apple extends Food {
- public void eat(){
- System.out.println("Apple eatting...");
- }
- }
- class AK47 extends Weapon {
- public void shoot(){
- System.out.println("AK47 shooting...");
- }
- }
- //抽象工厂类
- abstract class AbstractFactory {
- public abstract Vehicle createVehicle();
- public abstract Weapon createWeapon();
- public abstract Food createFood();
- }
- //具体工厂类,其中Food,Vehicle,Weapon是抽象类
- 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();
- }
- }
- //测试类
- public class TestDemo {
- public static void main(String[] args) {
- AbstractFactory f = new DefaultFactory();
- Vehicle v = f.createVehicle();
- v.run();
- Weapon w = f.createWeapon();
- w.shoot();
- Food a = f.createFood();
- a.eat();
- }
- }
抽象工厂方法从纵向上看,几乎没有可扩展性,假如我们想增加一个产品C,也就是说产品家族由原来的2个变为3个,程序将会有很大的变动,抽象工厂中就需要增加一个方法。这严重违背了开闭原则。并且抽象类是不喜欢被修改的。但是从横向上来看,却对扩展性有了很好的支持,如果我们增加一个产品等级3,我们只需要在写一个Create3就可以了,这里又符合了开闭原则,有多少个产品等级就应该有多少个实现工厂类。每增加一个产品等级就相应的增加一个实现工厂类,这里的扩展性又很自然的体现出来了。
所以每个模式都是必须在合适的地方使用的。
五、三种模式比较
1) 工厂方法模式和简单工厂模式在定义上是有很大不同的。工厂方法模式的核心是一个抽象工厂类,而简单工厂模式的核心却是一个实体类。
2) 工厂方法模式可以允许很多实的工厂类从抽象工厂继承下来,从而可以在实际上成为多个简单工厂模式的综合,达到了推广简单工厂模式的目的。
3) 反之,简单工厂模式是由工厂方法模式退化而来的。如果系统只需要一个实工厂类,那么不妨将抽象工厂类合并到实的工厂类中去,这样就退化到简单工厂模式了。
4) 对于抽象工厂模式,抽象产品可能是一个或多个,从而构成一个或多个产品族,但是工厂方法模式只能够是单一产品族。也就是说当抽象工厂模式中只有一个产品族的时候就退化到工厂方法模式了。
六、总 结
1) 简单工厂模式是由一个具体的类去创建其他类的实例,父类是相同的,父类是具体的。
2) 工厂方法模式是由一个抽象的父类定义公共接口,子类负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成。
3) 抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。它针对的是有多个产品的等级结构。而工厂方法模式针对的是一个产品的等级结构。
参考博客地址:http://www.cnblogs.com/forlina/archive/2011/06/21/2086114.html