天天看点

设计模式-简单工厂模式(Simple Factory Pattern)

推荐:​​Java设计模式汇总​​

简单工厂模式

定义

设计一个工厂类,给工厂类中创建产品实例的方法传入参数来决定创建哪一种产品类的实例。

简单工厂模式是属于创建型模式,又叫做静态工厂方法模式。

类型

创建型,但不属于GOF23种设计模式。

例子

Video类,所有视频的抽象。

package com.kaven.design.pattern.creational.simplefactory;

public abstract class Video {
    public abstract void produce();
}      

JavaVideo类,Java视频类,继承Video类。

package com.kaven.design.pattern.creational.simplefactory;

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

PythonVideo类,Python视频类,继承Video类。

package com.kaven.design.pattern.creational.simplefactory;

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

应用层代码:

package com.kaven.design.pattern.creational.simplefactory;

public class Test {
    public static void main(String[] args) {
        Video video = new JavaVideo();
        video.produce();
    }
}      

可见应用层代码太依赖对应的类。高层模块(应用层)不应该依赖低层模块(逻辑层),这违背了依赖倒置原则。

​​设计模式的七大原则​​

改进

增加一个工厂类。

package com.kaven.design.pattern.creational.simplefactory;

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

应用层代码:

package com.kaven.design.pattern.creational.simplefactory;

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

这样我们就不需要依赖对应的类了,只需要给工厂类传入类的标识字符串即可。

很容易发现,当产品类很多时,工厂类中创建产品实例的方法​​

​if-else​

​就会有很多,既不美观,也很容易出现错误。

再改进

工厂类代码:

package com.kaven.design.pattern.creational.simplefactory;

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

利用反射,就可以很好的解决这个问题了。

也很好的解决了违背开闭原则的问题,当有新产品产生时,我们不需要修改工厂中创建产品实例的方法的代码,我们只需要创建一个新的产品类即可,也就是对扩展开放,对修改关闭。

应用层代码:

package com.kaven.design.pattern.creational.simplefactory;

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

效果和第一次改进时一样,但代码的逼格看起来就高大上了不少。

工厂类中创建产品实例的方法我没有定义为静态方法,这个根据需求来定义吧。

适用场景

应用层只需要知道传入工厂类的参数,对于如何创建对象(逻辑)不需要关心。

优点

只需要传入一个正确的参数,就可以获取你所需要的对象,而无需知道其创建细节。