java设计模式学习笔记之简单工厂

一:简单工厂适用场景

1、工厂类负责创建的对象比较少

2、客户端(应用层)只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心

二:代码实现

1、假如现在有这样一个场景,某一学习视频网站上有java、python、c等视频课程,那现在肯定有一个视频类来创建这些视频。而且这个视频类里面的方法肯定是抽象的。

public abstract class Video {

    public abstract void produce();
}

2、现在我们创建一个录制java视频的类JavaVideo 来继承上面的抽象类Video,并实现produce方法。

public class JavaVideo extends Video{
    @Override
    public void produce() {
        System.out.println("录制Java课程视频");
    }
}

3、同理创建一个PythonVideo类。

public class PythonVideo extends Video{
    @Override
    public void produce() {
        System.out.println("录制Python视频");
    }
}

4、现在我们写一个测试类Test,现在我们的应用层(test类)是非常依赖具体的实现类的,那么有没有一种方法把整个生产过程放到一个类里边,使得应用层不依赖具体的实现类,这个就是简单工厂的由来。

public class test {
    public static void main(String[] args) {
        Video video1 = new JavaVideo();
        video1.produce();
        Video video2 = new PythonVideo();
        video2.produce();
    }
}

5、现在我们就把创建具体视频的过程移植到一个简单工厂VideoFactory类里面。

public class VideoFactory {
    public Video getVideo(String type) {
        if ("java".equalsIgnoreCase(type)){
            return new JavaVideo();
        }else if ("python".equalsIgnoreCase(type)){
            return new PythonVideo();
        }
        return null;
    }

}

6、这时候再来看一下应用层也就是Test类,现在这个类以及不依赖与具体的视频实现类了,只需要传入一个type就可以了。

public class Test {
    
    public static void main(String[] args) {
        VideoFactory videoFactory = new VideoFactory();
        Video video = videoFactory.getVideo("java");
        if (video == null){
            return;
        }
        video.produce();
    }
}

7、这就是简单工厂了,现在我们来看看UML图,现在Test类只依赖VideoFactory类,具体的生产过程都在VideoFactory类里面。

三:简单工厂的缺点

我们看上述具体工厂的实现类,很容易看出来简单工厂的一个缺点,那就是一旦我们要加一个课程(比如说C++)进去,那么工厂实现类的代码同样也是要修改的,所以简单工厂是不符合开闭原则的,当然工厂方法和抽象工厂是可以解决这个问题的,但这里暂时不谈,这里我们用另外一种方法来弥补这种不足。

四:利用java的反射来弥补简单工厂的扩展性

1、首先是工厂类代码的修改,异常直接捕获或者抛出来都可以。

public class VideoFactory {

    public Video getVideo(Class c) {
        Video video = null;
        try {
            video = (Video) Class.forName(c.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return video;
    }

}

2、现在来看我们的Test类,现在如果新增一个课程C语言,那么工厂类的代码是不需要修改的,只需要在Test里面传入这个课程的类(CVideo.class)就可以了,这样就从一定程度上满足了开闭原则。

public class Test {

    public static void main(String[] args) {
        VideoFactory videoFactory = new VideoFactory();
        Video video = videoFactory.getVideo(JavaVideo.class);
        if (video == null){
            return;
        }
        video.produce();
    }
}

五:jdk源码中使用简单工厂方法的类

1、现在我们来看一看简单工厂在jdk源码中的一些体现,首先我们来看一下calendar类,我这里用的是idea编辑器,快捷键是ctrl+shift+n来查看具体文件,进入calendar.java源文件。

2、找到calendar类里面的getInstance方法,并进入createCalendar方法。idea编辑器查看一个类里面的所有方法的快捷键是Ctrl+F12。只是calendar类里面的简单工厂是用switch-case实现的,但原理跟if-else是一样的。

猜你喜欢

转载自blog.csdn.net/qq_35156733/article/details/88868225
今日推荐