工厂模式结合反射——遵循开闭原则

目录

介绍

工厂模式是一种创建型模式,在工厂模式中,创建对象时不会对客户端暴露创建细节(将创建的代码封装到一个工厂类中),而是通过一个接口指向由工厂类创建并返回的对象。
对于设计模式和各个原则来说,无非就是要实现代码的高内聚和低耦合,还有尽量遵循开闭原则。开闭原则简单来说就是:软件中的对象(类,函数,模块)对扩展开放,对修改关闭。

于是,围绕开闭原则展开以下讨论。
传统工厂模式是如何违背了开闭原则的,工厂模式加反射机制是如何遵循开闭原则的。

以披萨为话题,我们要创建各种口味的披萨,例如奶酪披萨,水果披萨。
这个显然可以就通过工厂模式来实现,下面用传统工厂模式。
首先我们要声明一个IPizza接口:

public interface IPizza { 
    void eat();
}

IPizza的实现类:

//奶酪披萨
public class CheesePizza implements IPizza { 
    private String pizzaType="奶酪披萨";
    @Override
    public void eat() { 
        System.out.println(pizzaType+"真香!");
    }
}
//水果披萨
public class FruitPizza implements IPizza { 
    private String pizzaType="水果披萨";
    @Override
    public void eat() { 
        System.out.println(pizzaType+"真好吃!");
    }
}

下面通过工厂创建各种口味的披萨。

传统工厂模式

写一个工厂类,把创建各种口味披萨的任务交给它。

//披萨工厂类
public class PizzaFactory { 
    private PizzaFactory(){ }
    public static IPizza createPizza(String pizzaType){ 
        IPizza pizza=null;
        if ("奶酪披萨".equals(pizzaType)) { 
            pizza=new CheesePizza();
        } else if ("水果披萨".equals(pizzaType)) { 
            pizza=new FruitPizza();
        }
        return pizza;
    }
}

测试:

public class PizzaTest { 
    public static void main(String[] args) { 
        IPizza pizza=PizzaFactory.createPizza("水果披萨");
        pizza.eat();
        pizza=PizzaFactory.createPizza("奶酪披萨");
        pizza.eat();
    }
}

控制台结果:
《工厂模式结合反射——遵循开闭原则》
OK!就是那么简单,但是问题来了,我现在突然想到还有一种口味的披萨:蛋黄披萨。我想把它添加到系统中,要怎么做呢?
第一步,实现IPizza接口

//蛋黄披萨
public class EggyolkPizza implements IPizza { 
    private String pizzaType="蛋黄披萨";
    @Override
    public void eat() { 
        System.out.println(pizzaType+"贼香!");
    }
}

第二步,修改工厂类(emmm,思考一下,这是不是违背了开闭原则)

修改过程就是添加一个else if分支。

public class PizzaFactory { 
    private PizzaFactory(){ }
    public static IPizza createPizza(String pizzaType){ 
        IPizza pizza=null;
        if ("奶酪披萨".equals(pizzaType)) { 
            pizza=new CheesePizza();
        } else if ("水果披萨".equals(pizzaType)) { 
            pizza=new FruitPizza();
        } else if ("蛋黄披萨".equals(pizzaType)) { 
            pizza=new EggyolkPizza();
        }
        return pizza;
    }
}

代码搞定,测试一下:
《工厂模式结合反射——遵循开闭原则》
添加披萨口味是成功了,但是我们也违背了开闭原则,如果有很多个口味的披萨引进来,那我们岂不是要改工厂类改到吐?

工厂模式结合反射机制

同样也是写一个工厂类,把创建各种口味披萨的任务交给它。

public class PizzaFactory { 
    private PizzaFactory(){ }
    public static IPizza createPizza(String pizzaType){ 
        IPizza pizza=null;
        try { 
            Class clazz=Class.forName(pizzaType);
            pizza=(IPizza)clazz.newInstance();
        } catch (Exception e) { 
            e.printStackTrace();
        }
        return pizza;
    }
}

测试:

public class PizzaTest { 
    public static void main(String[] args) { 
        IPizza pizza=PizzaFactory.createPizza("cn.thg.community.pizza.impl.CheesePizza");
        pizza.eat();
        pizza=PizzaFactory.createPizza("cn.thg.community.pizza.impl.FruitPizza");
        pizza.eat();
    }
}

控制台结果:
《工厂模式结合反射——遵循开闭原则》
OK!
添加一个口味的披萨,还是蛋黄披萨吧。
很简单,只需要扩展多一个类就行了,不需要取修改工厂类。
只需一步,扩展一个蛋黄披萨的类

public class EggyolkPizza implements IPizza { 
    private String pizzaType="蛋黄披萨";
    @Override
    public void eat() { 
        System.out.println(pizzaType+"贼香!");
    }
}

测试:
《工厂模式结合反射——遵循开闭原则》
搞定。这样无论要加多少种口味,只需要拓展就行了,这不就很好的遵循了开闭原则吗,无论添加多少个披萨类,都不用对工厂类进行任何改变,直接在客户端(main方法)调用即可,相比较与传统工厂模式简直不要方便太多。

总结

很显然,传统工厂模式违背了开闭原则(扩展新口味要修改工厂类),而工厂模式结合反射的方式则没有违背。只不过是后者传参的方式变成了传全限定类名。

    原文作者:Candy_Tom
    原文地址: https://blog.csdn.net/Candy_Tom/article/details/108376379
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞