设计模式-工厂模式

简单工厂模式

简单工厂模式(Simple Factory Pattern)是指由一个工厂对象决定创建出哪一种产品类
的实例,但它不属于GOF,23 种设计模式

简单工厂适用
于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创
建对象的逻辑不需要关心。

接下来我们来看代码,还是以课程为例。咕泡学院目前开设有Java 架构、大数据、人工
智能等课程,已经形成了一个生态。我们可以定义一个课程标准ICourse 接口

/**
 * @program: HomeWork
 * @description: 课程
 * @author: hezhiqin
 * @create: 2019-09-24 10:27
 */
public interface ICourse {
    /**
    *@Description: 录制课程
    *@Param: 
    *@return: 
    *@Author: hezhiqin
    *@date: 2019/9/24
    */
    public  void  record();


}

创建一个Java 课程的实现JavaCourse 类

package simplefactroy;

/**
 * @program: HomeWork
 * @description: Java课程
 * @author: hezhiqin
 * @create: 2019-09-24 10:28
 */
public class JavaCourse implements  ICourse {
    public void record() {
        System.out.println("正在录制JAVA课程");
    }
}

看客户端调用代码,我们会这样写:

public static void main(String[] args) {
    ICourse course = new JavaCourse();
    course.record();
}

看上面的代码,父类ICourse 指向子类JavaCourse 的引用,应用层代码需要依赖
JavaCourse,如果业务扩展,我继续增加PythonCourse 甚至更多,那么我们客户端的
依赖会变得越来越臃肿。因此,我们要想办法把这种依赖减弱,把创建细节隐藏。虽然
目前的代码中,我们创建对象的过程并不复杂,但从代码设计角度来讲不易于扩展。现
在,我们用简单工厂模式对代码进行优化。先增加课程PythonCourse 类:
 

package simplefactroy;

/**
 * @program: HomeWork
 * @description: Python课程
 * @author: hezhiqin
 * @create: 2019-09-24 10:45
 */
public class PythonCourse  implements  ICourse{
    public void record() {
        System.out.println("正在录制Python课程");
    }
}

创建课程工厂类

package simplefactroy;

/**
 * @program: HomeWork
 * @description: 课程工厂
 * @author: hezhiqin
 * @create: 2019-09-24 10:30
 */
public class CourseFactroy {

//    public  ICourse create (String name){
//        if ("java".equals(name)){
//            return  new JavaCourse();
//        }else {
//            return null;
//        }
//
//    }


    public  ICourse create (String className){
        try {
            if (!(null==className||"".equals(className)))
                return  (ICourse)Class.forName(className).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {

        }
        return null;
    }
}

修改客户端调用代码:

public class simpleFactroyTest {
    public static void main(String[] args) {
//        ICourse iCourse = new JavaCourse();
//        iCourse.record();
        CourseFactroy courseFactroy = new CourseFactroy();
        ICourse iCourse = courseFactroy.create("simplefactroy.JavaCourse");
        iCourse.record();
    }
}

简单工厂也有它的缺点:工厂类的职责相对过重,不易于扩展过于复杂的产品结构。

 

工厂方法模式

工厂方法模式(Fatory Method Pattern)是指定义一个创建对象的接口,但让实现这个
接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。

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

public interface ICourseFactroy {
    ICourse create();
}

在分别创建子工厂,JavaCourseFactory 类:

public class JavaFactroy implements ICourseFactroy {
    public ICourse create() {
        return new JavaCourse();
    }
}

PythonCourseFactory 类:

public class PythonCourseFactroy implements ICourseFactroy {
    public ICourse create() {
        return new PythonCourse();
    }
}

看测试代码:

public class Test {
    public static void main(String[] args) {
        ICourseFactroy factory = new PythonCourseFactroy();
        ICourse course = factory.create();
        course.record();
        factory = new JavaFactroy();
        course = factory.create();
        course.record();
    }
}

 

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

 

抽象工厂模式

抽象工厂模式(Abastract Factory Pattern)是指提供一个创建一系列相关或相互依赖
产品族
产品等级结构
一个产品等级结构
对象的接口,无须指定他们具体的类。

 

客户端(应用层)不依赖于产品类实例如何被创
建、实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起使用创建对
象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从
而使客户端不依赖于具体实现。
讲解抽象工厂之前,我们要了解两个概念产品等级结构和产品族,看下面的图:

 

从上图中看出有正方形,圆形和菱形三种图形,相同颜色深浅的就代表同一个产品族,
相同形状的代表同一个产品等级结构。同样可以从生活中来举例,比如,美的电器生产
多种家用电器。那么上图中,颜色最深的正方形就代表美的洗衣机、颜色最深的圆形代
表美的空调、颜色最深的菱形代表美的热水器,颜色最深的一排都属于美的品牌,都是
美的电器这个产品族。再看最右侧的菱形,颜色最深的我们指定了代表美的热水器,那
么第二排颜色稍微浅一点的菱形,代表海信的热水器。同理,同一产品结构下还有格力
热水器,格力空调,格力洗衣机。

再看下面的这张图,最左侧的小房子我们就认为具体的工厂,有美的工厂,有海信工厂,
有格力工厂。每个品牌的工厂都生产洗衣机、热水器和空调。

通过上面两张图的对比理解,相信大家对抽象工厂有了非常形象的理解。接下来我们来
看一个具体的业务场景而且用代码来实现。还是以课程为例,每个课程不仅要提供课程

的录播视频,而且还要提供老师的课堂笔记。相当
于现在的业务变更为同一个课程不单纯是一个课程信息,要同时包含录播视频、课堂笔
记甚至还要提供源码才能构成一个完整的课程。在产品等级中增加两个产品IVideo 录播
视频和INote 课堂笔记。

IVideo 接口:

public interface IVideo {

    public void record();
}

INote 接口:

public interface INote {

    public void edit();
}

然后创建一个抽象工厂CourseFactory 类:

public interface ICourseFactroy {
    ICourse createCourse();

    INote createNote();

    IVideo createVideo();
}

接下来,创建Java 产品族,Java 视频JavaVideo 类:

public class JavaVideo implements IVideo {
    public void record() {
        System.out.println("录制JAva视频");
    }
}

扩展产品等级Java 课堂笔记JavaNote 类:

public class JavaNote implements INote {
    public void edit() {
        System.out.println("录制JAVA笔记");
    }
}

创建Java 产品族的具体工厂JavaCourseFactory:

public class JAVACourseFactory implements  ICourseFactroy {
    public ICourse createCourse() {
        return new JavaCourse();
    }

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

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

然后创建Python 产品,Python 视频PythonVideo 类:

public class PythonVideo implements  IVideo {
    public void record() {
        System.out.println("录制Python 视频");
    }
}
public class PythonVideo implements  IVideo {
    public void record() {
        System.out.println("录制Python 视频");
    }
}

扩展产品等级Python 课堂笔记PythonNote 类:

public class PythonNote implements  INote {
    public void edit() {
        System.out.println("编写Python 笔记");
    }
}

创建Python 产品族的具体工厂PythonCourseFactory:

public class PythonCourseFactory implements ICourseFactroy {
    public ICourse createCourse() {
        return new PythonCourse();
    }

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

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

来看客户端调用:

public class AbastractFactoryTest {
    public static void main(String[] args) {
        ICourseFactroy iCourseFactroy = new JAVACourseFactory();
        iCourseFactroy.createCourse().record();
        iCourseFactroy.createNote().edit();
        iCourseFactroy.createVideo().record();
    }
}

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

 

1、规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂
的接口。
2、增加了系统的抽象性和理解难度。
但在实际应用中,我们千万不能犯强迫症甚至有洁癖。在实际需求中产品等级结构升级
是非常正常的一件事情。我们可以根据实际情况,只要不是频繁升级,可以不遵循开闭
原则。代码每半年升级一次或者每年升级一次又有何不可呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值