工厂模式

JAVA设计模式之工厂模式(简单工厂模式+抽象工厂模式+工厂方法模式)

 简单工厂模式(只是让我们容易更理解工厂模式,但本身并不属于23种设计模式中)
   为什么有?

    从面向对象的角度来看,当我们需要一个对象的时候,我们并不是自己去创建这个对象,而是直接获取一个对象,比如说,我们需要一辆宝马车,我们并不是自己去生产他,而是直接去4S店买一辆就可以了,我们并不需要关心这辆宝马车是怎么生产的,我们只要会开就可以了.这时候我们就需要一个工厂类去为我们初始化这些对象.

   核心思想:使我们轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程.    

实现:
  1. public class CarFactory {
  2. /**
  3. * 简单工厂模式
  4. */
  5. public static Car getCar(String carName) {
  6. if(carName == "ford"){
  7. return new FordCar();
  8. }else if(carName == "handa"){
  9. return new HandaCar();
  10. }else if(carName == "benz"){
  11. return new BenzCar();
  12. }else{
  13. return null;
  14. }
  15. }
  16. }
   这是最简单的简单工厂模式的实现,但是这有一个很明显的缺点,那就是这种程序太不灵活了.比如说,我现在需要一台宝马车,那我们还需要在工厂中再添加一个if  else 的语句,但是修改过后我们还需要重新编译,发布,在部署到服务器中,这显然是十分麻烦的,如果我们需要生产几百种品牌的车,这样写出来的代码将是垃圾的,难以维护的代码,那么我们怎么解决这个问题呢?
答案是通过反射做到灵活的创建对象.
具体代码:
  1. public static Car getCar() throws Exception{
  2. Config config = Config.getInstance();
  3. String carName = config.getProperty("car");
  4. return (Car) Class.forName(carName).newInstance();
  5. }
首先创建一个配置文件,来告诉程序需要建立哪个对象的实例,传入该实例的全路径类名;
  1. car = simplefactory.BenzCar
然后通过读取配置文件,来获得全路径类名并创建对象
  1. properties.load(new FileInputStream(new File("src/simplefactory/car.properties")));
       这样我们就可以再不改变任何代码的情况下,通过配置文件来管理汽车工厂里生产的汽车的种类,省去了永无止境的if else判断,也省去了反复的的编译发布部署.使程序的灵活性大大增强,这就是简单工厂模式.

抽象工厂模式

     我们再来看刚才的这个例子,发现还是有与我们面向对象编程不符的的情况,哪里呢?
在我们的生活中,不可能会有一家工厂可以生产所有牌子的汽车,福特汽车必须要有福特汽车的工厂进行生产,奔驰汽车也必须由奔驰汽车的工厂来生产,这样,我们原来的的工厂类就变成了一个工厂接口,我们需要由福特工厂奔驰工厂去实现这个工厂类.这样就可以实现通过自家的工厂来生产自家的的汽车了.
    那么有人就会问了?我们为什么需要这么麻烦呢?难道就是为了单纯的符合面向对象?符合成活中的例子?就需要分别对每一个类创建一个单独的工厂,难道不知道这样会使我们的代码复杂性大大的增加吗?
    当然不是,这样做自然有必须这样做的道理.因为这样可以解决一些仅仅通过简单工厂模式无法解决的问题,
    下面我们来看一个问题:
     在简单工厂模式中,我们首先获取配置文件中的全路径的类名,在通过全路径的类名来得到他的Class类,最后在根据Class类的newInstance()的方法创建该类的实例对象,这看上去一切仿佛顺理成章,但是不知道大家注意到没有,newInstance()这个方法调用的是该类的无参的构造方法,如果有一个汽车类没有无参的构造方法呢?我们的简单工厂模式是不是就没有办法使用了呢?
        又有人会说了,我们不会调用Class的其他的创建实例方法吗?当然可以,但是当你用了其他的方法的时候,你的无参的这个方法是不是就不能用了呢?
        所以说,这样就会导致你的这个代码的通用性很差,甚至又回到了最开始那种无限if else的状态,这时候我们就需要使用到我们刚才说的抽象工厂模式来解决.
        抽象工厂模式,顾名思义,就是他的工厂是抽象的,可以用来产出各种,各不相同的实例.简单工厂模式只能说是抽象工厂模式的一种特殊情况.
  1. public class FordCar implements Car {
  2. private String color;
  3. public FordCar(String color){
  4. this.color = color;
  5. }
  6. @Override
  7. public void run() {
  8. System.out.println("我是福特轿车.屌丝专属!");
  9. }
  10. }
       在这个福特轿车类中,没有默认无参的构造构造方法,所以使用通用的构造方法是无法创建实例对象的,我们必须为其简历单独的工厂..
  1. public class FordCarFactory implements CarFactory {
  2. @Override
  3. public Car getCar() {
  4. return new FordCar("blue");
  5. }
  6. }
   在这里,我们为其设置里颜色属性之后就能顺利创建福特车啦.

    工厂方法模式

    4S店卖轿车,只是生活中的一种情况,在这种境况下,4S店和轿车并不是紧密耦合的关系,4S店只是持有了汽车的一个接口,并没有持有具体的实现类,也就是说他既可以卖福特轿车也可以买奔驰轿车.
    大家都知道我们生活中还有一种直营店模式,就是4S店和具体的轿车品牌绑定的,也就是说,我要买福特车只能去福特车的4S店.这在我们的程序中又该如何实现呢?
    首先我们需要有一个抽象的4S店类,分别由福特4S店/奔驰4S/本田4S店去继承,4S店有一个售卖轿车的方法;
  1. public abstract class I4S {
  2. public Car sellCar(){
  3. return null;
  4. };
  5. }
这里我们需要返回一个轿车,但是呢,这个抽象的4S点并没有和任何的轿车的工厂相绑定,那我们怎么给他一个轿车返回呢?下面有个很巧妙的解决方法:
  1. public Car sellCar(){
  2. return getCar();
  3. };
  4. public abstract Car getCar();
我们声明了一个抽象的getCar()方法,为父类提供了一个car对象(因为这是一个抽象的的方法,.并没有具体实现,所以实际上,这个car对象是不存在的,仅仅相当于一个占位符罢了),然后我们在具体的子类中实现该方法,为其返回一个子类的对象;
  1. public class HandaCar4S extends I4S {
  2. private HandaCarFactory handaCarFactory;
  3. @Override
  4. public Car getCar() {
  5. return handaCarFactory.getCar();
  6. }
  7. }
这就是工厂方法模式的核心,父类需要的对象有具体的子类来提供;





原文地址:https://www.cnblogs.com/Jxiaobai/p/6617508.html