三:java设计模式之工厂模式

眉间皱痕 提交于 2019-12-03 14:02:00

一、工厂模式的作用,为什么要用工厂模式?

a.工厂模式是为了解耦:把对象的创建和使用的过程分开。就是Class A 想调用Class B,那么只是调用B的方法,而至于B的实例化,就交给工厂类。

b.工厂模式可以降低代码重复。如果创建B过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。可以把这些创建对象B的代码放到工厂里统一管理。既减少了重复代码,也方便以后对B的维护。

c.工厂模式可以减少错误,因为工厂管理了对象的创建逻辑,使用者不需要知道具体的创建过程,只管使用即可,减少了使用者因为创建逻辑导致的错误。

 

二、工厂模式的一些适用场景。

 对象的创建过程/实例化准备工作很复杂,需要很多初始化参数,查询数据库等。

类本身有好多子类,这些类的创建过程在业务中容易发生改变,或者对类的调用容易发生改变。

 

 

三、简单工厂模式。

创建一个工厂类,在类中通过传入的参数不同创建不同的实体类。有新需求时需要更改工厂类中的代码,违背了开闭原则。

//创建抽象产品类 ,定义具体产品的公共接口;
interface ICourse {
    /**
     * 录制视频
     * @return
     */
    void record();
}

//创建具体产品类(继承抽象产品类), 定义生产的具体产品;
class JavaCourse implements ICourse {

    public void record() {
        System.out.println("录制Java课程");
    }
}

class PythonCourse implements ICourse {

    public void record() {
        System.out.println("录制Python课程");
    }
}  
//第一种方式,根据参数来判断哪个类来处理。
//新建工厂。
class CourseFactory {
 ICourse create(String name){
        if("java".equals(name)){
            return new JavaCourse();
        }else if("python".equals(name)){
            return new PythonCourse();
        }else {
            return null;
        }
    }
}
//调用工厂类来实例化需要的类。
class testFactory(){
    public static void main(String[] args) {
        CourseFactory factory = new CourseFactory();
        ICourse course = factory.create("Java");
        course.record();
    }
} 

 

//第二种写法,通过反射的方式
    public ICourse create(String className){
        try {
            if (!(null == className || "".equals(className))) {
                return (ICourse) Class.forName(className).newInstance();
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

//调用(通过全路径去反射获取)
  ICourseFactory factory = new ICourseFactory();
    ICourse course = factory.create("com.gupaoedu.vip.pattern.factory.JavaCourse");
    course.record();


或者

 public ICourse create(Class<? extends ICourse> clazz) {
    try {
      if (null != clazz) {
        return clazz.newInstance();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

//调用
    CourseFactory factory = new CourseFactory();
    ICourse course = factory.create(JavaCourse.class);
    course.record();

简单工厂模式的优点:

1、工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;

2、简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。

3、客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。

4、通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

 

简单工厂模式的缺点:

1、由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。

2、使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。

3、系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

4、简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。

简单工厂模式的在JDK或者Spring当中的运用例子:

待补充

四、工厂方法模式

工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。

主要是将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类。

//步骤1: 创建抽象工厂类,定义具体工厂的公共接口
public interface ICourseFactory {
    ICourse create();
}

//步骤2: 创建抽象产品类 ,定义具体产品的公共接口;
public interface ICourse {
    void record();
}

//步骤3: 创建具体产品类(继承抽象产品类), 定义生产的具体产品;
//产品1
public class JavaCourse implements ICourse {

    public void record() {
        System.out.println("录制Java课程");
    }
}
//产品2
public class PythonCourse implements ICourse {

    public void record() {
        System.out.println("录制Python课程");
    }
}


//步骤4:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法(每个产品对应一个实现的工厂);
//工厂1
public class JavaCourseFactory implements ICourseFactory {
    public ICourse create() {
        return new JavaCourse();
    }
}

//工厂2
public class PythonCourseFactory implements ICourseFactory {

    public ICourse create() {
        return new PythonCourse();
    }
}

//步骤5:外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例
public class FactoryMethodTest {

    public static void main(String[] args) {
        ICourseFactory factory = new PythonCourseFactory();
        ICourse course = factory.create();
        course.record();

        factory = new JavaCourseFactory();
        course = factory.create();
        course.record();
    }
}

工厂方法模式的优点:

1、更符合开-闭原则 
新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可

2、符合单一职责原则 
每个具体工厂类只负责创建对应的产品

3、不使用静态工厂方法,可以形成基于继承的等级结构。

工厂方法模式的缺点:

1、添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;

2、由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

3、虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;

4、一个具体工厂只能创建一种具体产品

工厂方法模式的在JDK或者Spring当中的运用例子:

待补充

五、抽象工厂模式

为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

代码和工厂方法模式类似,只是抽象工厂不但可以创建单个产品,而且还能创建产品族(关联产品)

//步骤1: 创建抽象工厂类,定义具体工厂的公共接口
public interface ICourseFactory {
      INote createNote();

    IVideo createVideo();
}

//步骤2: 创建抽象产品类 ,定义具体产品的公共接口(多个相关产品,形成产品族);
//笔记
public interface INote {
    void edit();
}
//视频
public interface IVideo {
    void record();
}


//步骤3: 创建具体产品类(继承抽象产品类), 定义生产的具体产品;
//产品1
public class JavaNote implements INote {

    public void edit() {
        System.out.println("编写Java笔记");
    }
}

//产品2
public class JavaVideo implements IVideo {
    public void record() {
        System.out.println("录制Java视频");
    }
}



//步骤4:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法(每个产品对应一个实现的工厂);
//只需要一个工厂,就能处理上面多种关联产品,如果产品之前存在关联关系,那么可以直
//接在此工厂内部进行维护
public class JavaCourseFactory implements CourseFactory {

    public INote createNote() {
        return new JavaNote();
    }

    public IVideo createVideo() {
        return new JavaVideo();
    }
}


//步骤5:外界通过调用具体工厂类的方法,创建多个产品。
public class FactoryMethodTest {

    public static void main(String[] args) {

        JavaCourseFactory factory = new JavaCourseFactory();

        factory.createNote().edit();
        factory.createVideo().record();

    }
}

抽象工厂模式的优点:

        抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

抽象工厂模式的缺点:

       产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

 

抽象工厂在JDK和Spring中的运用:

待补充

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!