• 工厂模式总结


    1.简单工厂——一个工厂创建多类产品(对象)

    简单工厂模式(SimpleFactory Pattern)是指由一个工厂对象决定创建出哪一种产品类的实例,但它不属于GOF,23种设计模式(参考资料:http://en.wikipedia.org/wiki/Design_Patterns#Patterns_by_Type)。简单工厂适用于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数(类的名字,或者类的class对象),对于如何创建对象的逻辑不需要关心。以课程为例,首先创建接口及其具体的实现:

    1 package com.gupaoedu.vip.pattern.factory;
    2 
    3 public interface ICourse {
    4     //录制课程
    5     void record();
    6 }
    1 package com.gupaoedu.vip.pattern.factory;
    2 
    3 public class JavaCourse implements ICourse {
    4     @Override
    5     public void record() {
    6         System.out.println("录制Java课程...");
    7     }
    8 }
    1 package com.gupaoedu.vip.pattern.factory;
    2 
    3 public class PythonCourse implements ICourse {
    4     @Override
    5     public void record() {
    6         System.out.println("录制python课程");
    7     }
    8 }

    简单工厂:

     1 package com.gupaoedu.vip.pattern.factory.simplefactory;
     2 import com.gupaoedu.vip.pattern.factory.ICourse;
     3 import com.gupaoedu.vip.pattern.factory.JavaCourse;
     4 import com.gupaoedu.vip.pattern.factory.PythonCourse;
     5 
     6 /**
     7  * 简单工厂,一个工厂可以创建不同的产品(对象)
     8  */
     9 public class CourseFactory {
    10     public ICourse create(String name) {
    11         if ("java".equals(name)) {
    12             return new JavaCourse();
    13         } else if("python".equals(name)){
    14             return new PythonCourse();
    15         } else {
    16             return null;
    17         }
    18     }
    19 }

    客户端调用:

     1 package com.gupaoedu.vip.pattern.factory.simplefactory;
     2 
     3 import com.gupaoedu.vip.pattern.factory.ICourse;
     4 import org.apache.log4j.BasicConfigurator;
     5 import org.slf4j.Logger;
     6 import org.slf4j.LoggerFactory;
     7 
     8 import java.util.Calendar;
     9 
    10 /**
    11  * 简单工厂模式,
    12  * 只适用于产品比较少,创建逻辑比较简单的场景
    13  */
    14 public class SimpelFactoryTest {
    15 
    16     public static void main(String[] args) {
    17         //创建工厂
    18         CourseFactory factory = new CourseFactory();
    19         //从工厂获得对象,不必每次都手动new ICourse,缺点,参数传入错误,则获取不到对象
    20         ICourse course = factory.create("java");
    21         course.record();
    22         course = factory.create("python");
    23         course.record();
    24     }
    25 }

    上面的简单工厂存在的问题:如果要新增一个课程,那么工厂类的代码就必须要修改,不符合开闭原则,另外,传入参数错误,将获取不到正确的对象,因此,对工厂类CourseFactory做如下改进:

     1 package com.gupaoedu.vip.pattern.factory.simplefactory;
     2 
     3 import com.gupaoedu.vip.pattern.factory.ICourse;
     4 
     5 /**
     6  * 简单工厂,一个工厂可以创建不同的产品(对象)
     7  */
     8 public class CourseFactory {
     9    /* public ICourse create(String name) {
    10         if ("java".equals(name)) {
    11             return new JavaCourse();
    12         } else if("python".equals(name)){
    13             return new PythonCourse();
    14         } else {
    15             return null;
    16         }
    17     }*/
    18     //简单工厂的改进,使用反射机制获取对象
    19     public ICourse create(Class clazz) {
    20         try {
    21             if (null != clazz) {
    22                 return (ICourse) clazz.newInstance();
    23             }
    24         } catch (Exception e) {
    25             e.printStackTrace();
    26         }
    27         return null;
    28     }
    29 }

    调用代码:

     1 package com.gupaoedu.vip.pattern.factory.simplefactory;
     2 
     3 import com.gupaoedu.vip.pattern.factory.ICourse;
     4 import com.gupaoedu.vip.pattern.factory.JavaCourse;
     5 import com.gupaoedu.vip.pattern.factory.PythonCourse;
     6 
     7 /**
     8  * 简单工厂模式,
     9  * 只适用于产品比较少,创建逻辑比较简单的场景
    10  */
    11 public class SimpelFactoryTest {
    12 
    13     public static void main(String[] args) {
    14         //创建工厂
    15         CourseFactory factory = new CourseFactory();
    16         //从工厂获得对象,不必每次都手动new ICourse,缺点,参数传入错误,则获取不到对象
    17     /*    ICourse course = factory.create("java");
    18         course.record();
    19         course = factory.create("python");
    20         course.record();*/
    21 
    22         ICourse javaCourse = factory.create(JavaCourse.class);
    23         javaCourse.record();
    24         ICourse pythonCourse = factory.create(PythonCourse.class);
    25         pythonCourse.record();
    26 
    27     }
    28 }

    2.工厂方法模式(一个工厂只生产一种产品(创建一种对象))

    工厂方法模式(FatoryMethodPattern)是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。在工厂方法模式中用户只需要关心所需产品对应的工厂,无须关心创建细节,而且加入新的产品符合开闭原则。工厂方法模式主要解决产品扩展的问题,在简单工厂中,随着产品链的丰富,如果每个课程的创建逻辑有区别的话,工厂的职责会变得越来越多,有点像万能工厂,并不便于维护。根据单一职责原则我们将职能继续拆分,专人干专事Java课程由Java工厂创建,Python 课程由 Python 工厂创建,对工厂本身也做一个抽象。来看代码,先创建
    ICourseFactory接口:(Icourse接口,JavaCourse PythonCourse类不变)

     1 package com.gupaoedu.vip.pattern.factory.factorymethod;
     2 
     3 import com.gupaoedu.vip.pattern.factory.ICourse;
     4 
     5 /**
     6  * 工厂方法模式,一个工厂只能创建一种 产品(返回一种对象)
     7  * 这里接口还可以改为抽象类,把一些公共的处理放到抽象类里面
     8  */
     9 public interface ICourseFactory {
    10     ICourse create(); //这个接口不活,让它的子类干活
    11 }

    分别创建2个实现类,返回不同的工厂

     1 package com.gupaoedu.vip.pattern.factory.factorymethod;
     2 
     3 import com.gupaoedu.vip.pattern.factory.ICourse;
     4 import com.gupaoedu.vip.pattern.factory.JavaCourse;
     5 
     6 /**
     7  * 单一职责,这个工厂只能创建JavaCourse;不同的产品用不同的工厂创建;不同的工厂去负责差异化的创建逻辑
     8  */
     9 public class JavaCourseFactory implements  ICourseFactory {
    10     @Override
    11     public ICourse create() {
    12         return new JavaCourse(); //这个工厂只能创建JavaCourse,直接new即可
    13     }
    14 }
     1 package com.gupaoedu.vip.pattern.factory.factorymethod;
     2 
     3 import com.gupaoedu.vip.pattern.factory.ICourse;
     4 import com.gupaoedu.vip.pattern.factory.PythonCourse;
     5 
     6 public class PythonCourseFactory implements ICourseFactory {
     7     @Override
     8     public ICourse create() {
     9         return new PythonCourse();
    10     }
    11 }

    调用:

     1 package com.gupaoedu.vip.pattern.factory.factorymethod;
     2 
     3 import com.gupaoedu.vip.pattern.factory.ICourse;
     4 
     5 public class FactoryMethodTest {
     6     public static void main(String[] args) {
     7         ICourseFactory  factory = new PythonCourseFactory();
     8         ICourse course = factory.create();
     9         course.record();
    10     }
    11 }

     工厂方法适用于以下场景:

    (1)创建对象需要大量重复的代码。
    (2)客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
    (3)一个类通过其子类来指定创建哪个对象。
    工厂方法也有缺点:
    (1)类的个数容易过多,增加复杂度。
    (2)增加了系统的抽象性和理解难度

     三,抽象工厂模式

    抽象工厂模式(Abastract Factory Pattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。客户端(应用层)不依赖于产品类实例如何被创建、实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。理解抽象工厂之前,先了解两个概念:

    产品等级结构和产品族,看下面的图:

    同种类称为同等级,同相同等级的一类产品可以由不同的工厂生产,这些不同工厂生产出来的同一类产品,称之为一个产品等级

    同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,下图 所示的是海尔工厂和 TCL 工厂所生产的电视机与空调对应的关系图。

    (图片摘自http://c.biancheng.net/view/1351.html )

    现在假设上面的课程进行了升级,现在的业务变更为同一个课程不单纯是一个课程信息,要同时包含录播视频、课堂笔记,甚至还要提供源码才能构成一个完整的课程。在产品等级中增加两个产品IVideo录播

    视频和INote课堂笔记。

    1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
    2 
    3 public interface ICourse {
    4     //录制课程
    5     void record();
    6 }
    1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
    2 
    3 public interface INote {
    4     void edit();//记笔记
    5 }
    1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
    2 
    3 public interface IVideo {
    4     void record();
    5 }
     1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
     2 
     3 import com.gupaoedu.vip.pattern.factory.ICourse;
     4 
     5 /**
     6  * 要求所有的子工厂都实现 这个工厂
     7  * 一个品牌的抽象
     8  */
     9 public interface ICourseFactory {
    10     ICourse createCourse();
    11     //不仅能创建课程,还能创建笔记和视频
    12     INote createNote();
    13 
    14     IVideo createVideo();
    15 }

    实现类:

    1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
    2 
    3 public class JavaCourse implements ICourse {
    4     @Override
    5     public void record() {
    6         System.out.println("录制Java课程...");
    7     }
    8 }
    1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
    2 
    3 public class PythonCourse implements ICourse {
    4     @Override
    5     public void record() {
    6         System.out.println("录制python课程");
    7     }
    8 }
    1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
    2 
    3 public class JavaNote implements INote {
    4     @Override
    5     public void edit() {
    6         System.out.println("编写java笔记");
    7     }
    8 }
    1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
    2 
    3 public class PythonNote implements INote {
    4     @Override
    5     public void edit() {
    6         System.out.println("编写python笔记");
    7     }
    8 }
    1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
    2 
    3 public class JavaVideo implements IVideo {
    4     @Override
    5     public void record() {
    6         System.out.println("录制java视频");
    7     }
    8 }
    1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
    2 
    3 public class PythonVideo implements IVideo {
    4     @Override
    5     public void record() {
    6         System.out.println("录制python视频");
    7     }
    8 }

    工厂的实现类:每个工厂都可以生产三种产品

     1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
     2 
     3 import com.gupaoedu.vip.pattern.factory.ICourse;
     4 import com.gupaoedu.vip.pattern.factory.JavaCourse;
     5 
     6 public class JavaCourseFactory implements ICourseFactory {
     7     @Override
     8     public ICourse createCourse() {
     9         return new JavaCourse();
    10     }
    11 
    12     @Override
    13     public INote createNote() {
    14         return new JavaNote();
    15     }
    16 
    17     @Override
    18     public IVideo createVideo() {
    19         return new JavaVideo();
    20     }
    21 }
     1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
     2 
     3 import com.gupaoedu.vip.pattern.factory.ICourse;
     4 import com.gupaoedu.vip.pattern.factory.PythonCourse;
     5 
     6 public class PythonCourseFactory implements ICourseFactory {
     7     @Override
     8     public ICourse createCourse() {
     9         return new PythonCourse();
    10     }
    11 
    12     @Override
    13     public INote createNote() {
    14         return new PythonNote();
    15     }
    16 
    17     @Override
    18     public IVideo createVideo() {
    19         return new PythonVideo();
    20     }
    21 }

    测试类:

     1 package com.gupaoedu.vip.pattern.factory.abstractfactory;
     2 
     3 public class AbstractFactoryTest {
     4     public static void main(String[] args) {
     5         ICourseFactory factory = new JavaCourseFactory();
     6         //同一个工厂创建多个产品;同一个产品可以被不同的工厂创建
     7          factory.createCourse().record();
     8          factory.createNote().edit();
     9          factory.createVideo().record();
    10 
    11          //python工厂
    12         PythonCourseFactory pythonCourseFactory = new PythonCourseFactory();
    13         pythonCourseFactory.createCourse().record();
    14         pythonCourseFactory.createNote().edit();
    15         pythonCourseFactory.createVideo().record();
    16     }
    17 }

     上面的代码完整地描述了两个产品族Java课程和Python课程,也描述了两个产品等级视频和笔记。抽象工厂非常完美清晰地描述这样一层复杂的关系。但是如果我们再继续扩展产品等级,将源码Source也加入到课程中,那么我们的代码从抽象工厂,到具体工厂要全部调整,很显然不符合开闭原则。因此抽象工厂也是有缺点的:

    (1)规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂
    的接口。
    (2)增加了系统的抽象性和理解难度。

     三种工厂模式UML类图对比:

    简单工厂模式: 一个工厂创建所有对象(小作坊,什么都生产,工厂和产品一对多)

    工厂方法模式:创建工厂接口/抽象类,让子类去创建对象;一套产品分的零部件由不同的工厂生产,每个工厂只生产一种零部件(创建一类对象)(工厂和产品一对一)

    抽象工厂模式:不同工厂可以生产相同 的产品(产品族),一个产品可以给不同工厂去生产(产品等级),工厂和产品之间多对多的关系

     

     代码地址: https://github.com/liuch0228/GP-pattern

  • 相关阅读:
    Servlet的生命周期
    Servlet中的请求与响应
    Servlet中的相关的配置文件信息:
    转发与重定向的区别,笔记无法转过来,所以直接放链接了,可以直接查看
    JSP入门中的一些案例代码:
    一些已经有些模糊的小知识(一)
    JSP入门五之request,out,response对象的应用
    JSP入门四
    JSP入门三 不知道如何将笔记同步过来只能这样了
    来自(乐唯科技)的面试问题..
  • 原文地址:https://www.cnblogs.com/enjoyjava/p/11415781.html
Copyright © 2020-2023  润新知