简单工厂

  • 定义:由一个工厂对象决定创建出哪一种产品类的实例
  • 类型创建性,但不属于GOF23种设计模式
  • 适用场景

    • 工厂类负责创建的对象比较少
    • 客户端(应用层)只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心
  • 优点:只需要传入一个正确的参数,就可以获取你所需要的对象而无需知道其创建细节。
  • 缺点:工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则。

案例

public abstract class Video {    public abstract void produce();}
public class JavaVideo extends Video {    @Override    public void produce() {        System.out.println("录制Java课程视频");    }}
public class PythonVideo extends Video {    @Override    public void produce() {        System.out.println("录制Python课程视频");    }}
public class Test {    public static void main(String[] args) {        Video video = new PythonVideo();        video.produce();    }}

思考
Video video = new PythonVideo();这行在客户端的代码使得客户端不但知道了Video抽象类还知道了其实现类PythonVideo。接口的思想是“封装隔离”,而实现类PythonVideo应该是被抽象类Video封装并同客户端隔离开的,即客户端根本就应该不知道具体的实现类是PythonVideo。

于是乎我们就拿走new PythonVideo( );但是我们却无法得到Video对象。就像现在的Client,它知道要使用Video接口,但是不知道由谁实现,也不知道如何实现,从而得不到接口对象,就无法使用接口,那该怎么办?于是乎简单工厂就来了。

public class VideoFactory {    //【1】反射    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;    }    public Video getVideo(String type){        if("java".equalsIgnoreCase(type)){            return new JavaVideo();        }else if("python".equalsIgnoreCase(type)){            return new PythonVideo();        }        return null;    }}
public class Test {    public static void main(String[] args) {        VideoFactory videoFactory = new VideoFactory();        Video video = videoFactory.getVideo("java");        if(video == null){            return;        }        video.produce();/*        VideoFactory videoFactory = new VideoFactory();        Video video = videoFactory.getVideo(JavaVideo.class);        if(video == null){            return;        }        video.produce();*/    }}


问题:
如果需要增加其他类型的视频,就需要在VideoFactory中修改添加相应的代码,这个时候可以使用工厂方法