java老乌龟的博客

从现在起记录一点一滴

工厂模式

1工厂模式

在开发中会需要用到一些典型的对象,这些对象常常会用到,他们的归类是非常清晰的。例如常见的service,dao等等。这些东西大范围的在程序中做new操作会不太好,让人看得眼花缭乱。这时候我们迫切需要封装,提供一个get器。工厂就是一个成熟的get器,我们将之抽象为工厂,就像我需要一个自行车直接从工厂方法中去get就行了。工厂模式相对是比较简单的

工厂分为一般工厂和抽象工厂和静态工厂。

静态工厂就是一个静态工具类,以前在纯servlet的应用中大量的用到。即写一个配置文件,将接口名和实现的全类名写在一个properties文件中,当你需要一个dao的时候不需要去new daoImpl(),而是将这个dao的反射类对象传进工厂的静态方法,静态方法通过类对象拿到简单类名,然后到propertis中去拿到匹配的实现全类名,然后反射一个实例返回,这样就避免了再servlet中大量的去new这些对象。当然这也是不完美的。因为一万个servlet你就要掉一万次工厂方法。spring的做法是IOC。当然这里我们就不深入这个静态工厂了。我们来看看设计模式中最经典的工厂,即一般工厂和抽象工厂的用法:

1.1一般工厂

------------------------------------------------------------------------------------------------------------------

1.1.1 定义接口

/**
 * 移动接口
 * 功能:移动
 */
public interface Moveable {
    public void run();
}

移动接口抽象所有可移动的物体,

/**
 * 交通工具接口
 *
 */
public interface VehicleFactory{
    public Moveable create();
}
交通工具工厂接口,将交通工具制造厂的行为create抽象出来


1.1.2 实体类

public class Broom implements Moveable {
    @Override
    public void run() {
        System.out.println("宝马在跑.......");
    }
}

public class Car implements Moveable {
    @Override
    public void run() {
        System.out.println("小汽车在跑......");
    }
}
实体类实现了移动的接口,并实现run动作


1.1.3 工厂类

public class BroomFctory implements VehicleFactory {
    @Override
    public Moveable create() {
        // TODO Auto-generated method stub
        return new Broom();
    }
}

public class CarFactory implements VehicleFactory {
    @Override
    public Moveable create() {
        // TODO Auto-generated method stub
        return new Car();
    }
}
工厂类实现交通工具工厂接口,并实现创建交通工具的行为


1.1.4 客户端

public class Client {
    public static void main(String[] args) {
        VehicleFactory fac=new BroomFctory();
        Moveable move=fac.create();
        move.run();
    }
}


异常简单吧!就是封装了new操作而已。这就是传说中的一般工厂,作为面向对象的编程,把行为封装到对象,将对象的创建封装到工厂。

他有一个很深的缺点就是:

1)当产品很多并且类型归类不止一种类型的时候,就要写很多工厂类(一个工厂对应某一类产品)

2)针对不同的产品有不同的行为,如汽车是run,动物是eat, 武器是发射...........

一般工厂就暴露了无能的以免,我们迫切需要一种更为灵活的工厂来适应这类复杂的需求。




1.2抽象工厂

------------------------------------------------------------------------------------------------------------------

1.2.1抽象类

首先假设一个系统的开发我们需要用到三类产品:食物,武器,交通工具,这三类事物又有他们的很多子类,那么为了适应抽象工厂我们先写这几种类型的抽象类

/**
 * 食物
 */
public abstract class Food {
    /**
     * 打印名字
     */
    public abstract void printName();
}

/**
 * 交通工具
 */
public abstract class Vehicle {
    /**
     *      */
    public abstract void run();
}
/**
 * 武器类
 */
public abstract class Weapon {
    /**
     * 射击
     * */
    public abstract void shoot();
}

这些产品的类是抽象的,并且行为也是抽象的。因为我们不知道他们的子类会有那些行为。

1.2.2 添加实体类

实体类集成抽象类:


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

public class Broom extends Vehicle {
    @Override
    public void run() {
        System.out.println("宝马跑跑跑.....");
    }
}
魔法扫把

public class MagicStick extends Vehicle {
    @Override
    public void run() {
        System.out.println("魔法扫把跑跑跑.....");
    }
}
苹果

public class Apple extends Food {
    @Override
    public void printName() {
        System.out.println("apple");
    }
}
毒蘑菇

public class MushRoom extends Food {
    @Override
    public void printName() {
        System.out.println("毒蘑菇");
    }
}
汽车

public class Car extends Vehicle {
    @Override
    public void run() {
        System.out.println("小汽车啊跑跑跑.........");
    }
}

1.2.3抽象工厂

三个抽象类都抽象了所有的子类产品,那么抽象工厂也就久负责创建这些抽象类即可

/**
 * 抽象工厂
 */
public abstract class AbstractFactory {
    /**
     * 创建交通工具
     * @return
     */
    public abstract Vehicle createVehicle();

    /**
     * 创建武器
     * @return
     */
    public abstract Weapon createWeapon();

    /**
     * 创建食物
     * @return
     */
    public abstract Food createFood();
}

抽象工厂的的抽象方法都是抽象的,比如createFood()到底是返回什么食物?苹果?蘑菇?为什么要这样?


1.2.4 抽象工厂实现类

第一套实现

public class DefaultFactory extends AbstractFactory {
    @Override
    public Vehicle createVehicle() {
        return new Car();
    }

    @Override
    public Weapon createWeapon() {
        return new AK47();
    }

    @Override
    public Food createFood() {
        return new Apple();
    }
}

第二套实现

public class MyFactory extends AbstractFactory {
    @Override
    public Vehicle createVehicle() {
        return new MagicStick();
    }

    @Override
    public Weapon createWeapon() {
        return new AK47();
    }

    @Override
    public Food createFood() {
        return new MushRoom();
    }
}


1.2.5 测试

public static void main(String[] args) {
    //AbstractFactory f = new MyFactory();
    AbstractFactory f = new DefaultFactory();
    Vehicle v = f.createVehicle();
    v.run();
    Weapon w = f.createWeapon();
    w.shoot();
    Food a = f.createFood();
    a.printName();
}
就是说在现实开发中我们可以通过实现抽象工厂的具体实现即可完成对产品的切换,一个工厂实现负责一套产品。

如此我们可以在项目中使用,一套产品不满意只需要重新换一个工厂 ,源代码几乎不变。

如果把抽象的内容定义在配置文件中就可以做到只改配置文件  永远不需要动源代码。


长处

非常好的扩展性,新的工厂只需要继承抽象工厂即可

工厂的生产产品只需要是抽象类的子类即可

短处

定义需要很严密的思维 要花很多时间  代码量很大





















































阅读更多
个人分类: 设计模式
想对作者说点什么? 我来说一句

GankouNoodles.java

2018年05月23日 256B 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭