zoukankan      html  css  js  c++  java
  • 工厂模式

    JAVA设计模式之工厂模式(简单工厂模式+抽象工厂模式+工厂方法模式)

     简单工厂模式(只是让我们容易更理解工厂模式,但本身并不属于23种设计模式中)
       为什么有?

        从面向对象的角度来看,当我们需要一个对象的时候,我们并不是自己去创建这个对象,而是直接获取一个对象,比如说,我们需要一辆宝马车,我们并不是自己去生产他,而是直接去4S店买一辆就可以了,我们并不需要关心这辆宝马车是怎么生产的,我们只要会开就可以了.这时候我们就需要一个工厂类去为我们初始化这些对象.

       核心思想:使我们轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程.    

    实现:
    1. public class CarFactory {
    2. /**
    3. * 简单工厂模式
    4. */
    5. public static Car getCar(String carName) {
    6. if(carName == "ford"){
    7. return new FordCar();
    8. }else if(carName == "handa"){
    9. return new HandaCar();
    10. }else if(carName == "benz"){
    11. return new BenzCar();
    12. }else{
    13. return null;
    14. }
    15. }
    16. }
       这是最简单的简单工厂模式的实现,但是这有一个很明显的缺点,那就是这种程序太不灵活了.比如说,我现在需要一台宝马车,那我们还需要在工厂中再添加一个if  else 的语句,但是修改过后我们还需要重新编译,发布,在部署到服务器中,这显然是十分麻烦的,如果我们需要生产几百种品牌的车,这样写出来的代码将是垃圾的,难以维护的代码,那么我们怎么解决这个问题呢?
    答案是通过反射做到灵活的创建对象.
    具体代码:
    1. public static Car getCar() throws Exception{
    2. Config config = Config.getInstance();
    3. String carName = config.getProperty("car");
    4. return (Car) Class.forName(carName).newInstance();
    5. }
    首先创建一个配置文件,来告诉程序需要建立哪个对象的实例,传入该实例的全路径类名;
    1. car = simplefactory.BenzCar
    然后通过读取配置文件,来获得全路径类名并创建对象
    1. properties.load(new FileInputStream(new File("src/simplefactory/car.properties")));
           这样我们就可以再不改变任何代码的情况下,通过配置文件来管理汽车工厂里生产的汽车的种类,省去了永无止境的if else判断,也省去了反复的的编译发布部署.使程序的灵活性大大增强,这就是简单工厂模式.

    抽象工厂模式

         我们再来看刚才的这个例子,发现还是有与我们面向对象编程不符的的情况,哪里呢?
    在我们的生活中,不可能会有一家工厂可以生产所有牌子的汽车,福特汽车必须要有福特汽车的工厂进行生产,奔驰汽车也必须由奔驰汽车的工厂来生产,这样,我们原来的的工厂类就变成了一个工厂接口,我们需要由福特工厂奔驰工厂去实现这个工厂类.这样就可以实现通过自家的工厂来生产自家的的汽车了.
        那么有人就会问了?我们为什么需要这么麻烦呢?难道就是为了单纯的符合面向对象?符合成活中的例子?就需要分别对每一个类创建一个单独的工厂,难道不知道这样会使我们的代码复杂性大大的增加吗?
        当然不是,这样做自然有必须这样做的道理.因为这样可以解决一些仅仅通过简单工厂模式无法解决的问题,
        下面我们来看一个问题:
         在简单工厂模式中,我们首先获取配置文件中的全路径的类名,在通过全路径的类名来得到他的Class类,最后在根据Class类的newInstance()的方法创建该类的实例对象,这看上去一切仿佛顺理成章,但是不知道大家注意到没有,newInstance()这个方法调用的是该类的无参的构造方法,如果有一个汽车类没有无参的构造方法呢?我们的简单工厂模式是不是就没有办法使用了呢?
            又有人会说了,我们不会调用Class的其他的创建实例方法吗?当然可以,但是当你用了其他的方法的时候,你的无参的这个方法是不是就不能用了呢?
            所以说,这样就会导致你的这个代码的通用性很差,甚至又回到了最开始那种无限if else的状态,这时候我们就需要使用到我们刚才说的抽象工厂模式来解决.
            抽象工厂模式,顾名思义,就是他的工厂是抽象的,可以用来产出各种,各不相同的实例.简单工厂模式只能说是抽象工厂模式的一种特殊情况.
    1. public class FordCar implements Car {
    2. private String color;
    3. public FordCar(String color){
    4. this.color = color;
    5. }
    6. @Override
    7. public void run() {
    8. System.out.println("我是福特轿车.屌丝专属!");
    9. }
    10. }
           在这个福特轿车类中,没有默认无参的构造构造方法,所以使用通用的构造方法是无法创建实例对象的,我们必须为其简历单独的工厂..
    1. public class FordCarFactory implements CarFactory {
    2. @Override
    3. public Car getCar() {
    4. return new FordCar("blue");
    5. }
    6. }
       在这里,我们为其设置里颜色属性之后就能顺利创建福特车啦.

        工厂方法模式

        4S店卖轿车,只是生活中的一种情况,在这种境况下,4S店和轿车并不是紧密耦合的关系,4S店只是持有了汽车的一个接口,并没有持有具体的实现类,也就是说他既可以卖福特轿车也可以买奔驰轿车.
        大家都知道我们生活中还有一种直营店模式,就是4S店和具体的轿车品牌绑定的,也就是说,我要买福特车只能去福特车的4S店.这在我们的程序中又该如何实现呢?
        首先我们需要有一个抽象的4S店类,分别由福特4S店/奔驰4S/本田4S店去继承,4S店有一个售卖轿车的方法;
    1. public abstract class I4S {
    2. public Car sellCar(){
    3. return null;
    4. };
    5. }
    这里我们需要返回一个轿车,但是呢,这个抽象的4S点并没有和任何的轿车的工厂相绑定,那我们怎么给他一个轿车返回呢?下面有个很巧妙的解决方法:
    1. public Car sellCar(){
    2. return getCar();
    3. };
    4. public abstract Car getCar();
    我们声明了一个抽象的getCar()方法,为父类提供了一个car对象(因为这是一个抽象的的方法,.并没有具体实现,所以实际上,这个car对象是不存在的,仅仅相当于一个占位符罢了),然后我们在具体的子类中实现该方法,为其返回一个子类的对象;
    1. public class HandaCar4S extends I4S {
    2. private HandaCarFactory handaCarFactory;
    3. @Override
    4. public Car getCar() {
    5. return handaCarFactory.getCar();
    6. }
    7. }
    这就是工厂方法模式的核心,父类需要的对象有具体的子类来提供;





  • 相关阅读:
    SignalR Self Host+MVC等多端消息推送服务(3)
    SignalR Self Host+MVC等多端消息推送服务(2)
    [翻译 EF Core in Action 1.9] 掀开EF Core的引擎盖看看EF Core内部是如何工作的
    [翻译 EF Core in Action 1.8] MyFirstEfCoreApp应用程序设置
    [翻译 EF Core in Action 1.7] MyFirstEfCoreApp访问的数据库
    [翻译 EF Core in Action 1.6]你的第一个EF Core应用程序
    [翻译 EF Core in Action] 1.5 关于NoSql
    [翻译] EF Core 概述
    [翻译] 你将在本书中学到什么
    [翻译] 对正在使用EF6x开发人员的一些话
  • 原文地址:https://www.cnblogs.com/Jxiaobai/p/6617508.html
Copyright © 2011-2022 走看看