设计模式之简单工厂模式

来源:互联网 发布:java jsoup 爬虫实例 编辑:程序博客网 时间:2024/06/07 18:22

前言:

简单工厂模式是常用的设计模式,该模式解决了如何实例化对象的问题。

一. 简单工厂的简介:

1. 工厂的含义:工厂是一个负责创建对象的类。

2. 面向对象编程理解:

面向对象的编程,目的是为了让代码做到易维护、易扩展、易复用

生活中的实例: 像活字印刷术一样,一行文字,可以替换任意一个,也可以在任意位置新增一个字,每个字还可以重复使用,这使得字与字之间的耦合度,降到最低。

面向对象的编程中,用封装、继承、多态,来达到以上的目的,这就是面向对象的编程。设计模式就是为了更好的完成面向对象而服务的。

二. 简单工厂模式实例

案例:一个电子阅读器,中文模式和英文模式和日文模式等之间的语言切换功能的实现。

设计UML模型图:
UML模型图

  1. 产品的的抽象类:抽象类是具有相同属性和方法的提取类。本例中,所有的语言的阅读器都应该有显示show()功能,提取出来。
package com.pattern.service;/** * 多国语言阅读器接口 * @author 葫芦娃 * */public interface IReader {    //显示内容    void show();}

2 . 产品类:实现了抽象类的方法,并对此方法加上自己特有的功能实现(体现出类与类之间的重载和多态)。

中文阅读器:

package com.pattern.impl;import com.pattern.service.IReader;/** * 汉语阅读器 *  * @author 葫芦娃 * */public class ChineseReader implements IReader {    @Override    public void show() {        System.out.println("汉语阅读器:我爱你");    }}

英文阅读器:

package com.pattern.impl;import com.pattern.service.IReader;/** * 英语阅读器 *  * @author 葫芦娃 * */public class EnglishReader implements IReader {    @Override    public void show() {        System.out.println("英语阅读器:I LOVE YOU");    }}

日文阅读器:

package com.pattern.impl;import com.pattern.service.IReader;/** * 日语阅读器 *  * @author 葫芦娃 * */public class JapaneseReader implements IReader {    @Override    public void show() {        System.out.println("日语阅读器:私はあなたを愛して");    }}

3 . 工厂类:包含必要的逻辑判断,根据客户端选择条件,动态的实例化产品类.

package com.pattern.factory;import com.pattern.impl.ChineseReader;import com.pattern.impl.EnglishReader;import com.pattern.impl.JapaneseReader;import com.pattern.service.IReader;/** * 简单工厂类 *  * @author 葫芦娃 * */public class ReaderFactory {    /**     * 根据用户选择的语言,创建阅读器     *      * @param language     * @return IReader     */    public static IReader createReader(String language) {        IReader reader = null;        switch (language) {        case "Chinese":            reader = new ChineseReader();            break;        case "English":            reader = new EnglishReader();            break;        case "Japanese":            reader = new JapaneseReader();            break;        default:            reader = new ChineseReader();            break;        }        return reader;    }    /**     * 通过类名映射创建对象     * @param className     * @return     */    public static IReader createReaderByClassName(String className){        IReader reader = null;        try {            //通过反射的方式创建对象,解决分支判断问题            reader = (IReader) Class.forName(className).newInstance();        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        return reader;    }}

这里提供了两个方法作参考,第一个方法createReader()就是根据不同的情况,来判断创建哪一个语言的阅读器。

第二个方法createReaderByClassName()业实现了同样的功能,优点是利用“反射”的方式,通过传入不同的类名,创建与之对应对象。在实际的开发中,可以将输入的参数,保存在properties文件中,便于管理和维护,供你参考。

工厂类的作用:包含了必要的逻辑判断,根据客户端的选择条件,动态实例化相关的类。它解决了对在客户端创建对象过程的隐藏和封装,客户端无需了解对象的创建过程,直接通过参数,控制工厂,得到想要创建的对象实例。

简单工厂的缺点:每当新加一个产品,都要去修改工厂类,在工厂类中增加一个case分支条件,这就要修改原有代码,违反了开放-封闭原则。

开放-封闭原则:对扩展开放,对修改关闭的原则。新需求的增加不是要在原有代码上改来改去,而是要通过新增相关类的方式,实现对新功能的拓展,不影响原有功能的使用,降低代码间的耦合性。

4 . 客户端中的使用

客户端不管用哪个产品类的实例,只需要把参数名(如“Chinese”)传递给工厂,工厂自动就给出了相应的实例。

package com.pattern.client;import com.pattern.factory.ReaderFactory;import com.pattern.impl.ChineseReader;import com.pattern.impl.EnglishReader;import com.pattern.impl.JapaneseReader;import com.pattern.service.IReader;/** * 客户端类:调用工厂创建实例 *  * @author 葫芦娃 * */public class TestClient {    public static void main(String[] args) {        TestClient client = new TestClient();        // 通过关键字创建        client.testCreateReader();        //通过类名创建        client.testCreateReaderByClassName();    }    //测试工厂模式创建对象    private void testCreateReader() {        IReader cReader = ReaderFactory.createReader("Chinese");        cReader.show();        // 用户切换英语模式        IReader eReader = ReaderFactory.createReader("English");        eReader.show();        // 用户切换日语模式        IReader jReader = ReaderFactory.createReader("Japanese");        jReader.show();    }    //测试通过反射的方式获取对象    private void testCreateReaderByClassName() {        IReader cReader = ReaderFactory.createReaderByClassName("com.pattern.impl.ChineseReader");        cReader.show();        IReader eReader = ReaderFactory.createReaderByClassName(EnglishReader.class.getName());        eReader.show();        IReader jReader = ReaderFactory.createReaderByClassName(JapaneseReader.class.getName());        jReader.show();    }}

5 . 输出的结果

汉语阅读器:我爱你英语阅读器:I LOVE YOU日语阅读器:私はあなたを愛して汉语阅读器:我爱你英语阅读器:I LOVE YOU日语阅读器:私はあなたを愛して

三. 总结:

  1. 简单工厂实现了对如何创建对象过程的封装,客户端不在关心对象是如何实例化的,只需通过工厂,传入相关的参数,实例化对象。

  2. 简单工厂的缺点也就暴露了出来,如果我在新增一个功能(如:西班牙语阅读器),那就必须修改工厂类。如何解决这个问题呢?在下一章的工厂模式(点击查看)中将解决这个问题。

原创粉丝点击