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

    一、概述

    一般问题:在系统中,有时需要生产复杂对象,复杂性表现在:每次构造不同对象、对象的构造很复杂、对象的构造依赖具体环境等等。

    核心方案:定义一个用于创建对象的接口,让其决定实例化哪个类。

    设计意图:通常我们创建一个简单对象就是调用其new构造方法,同时也造成客户端和创建对象的耦合;如果是复杂对象,有必要对其解耦,工厂模式的初衷是封装复杂对象的new构造函数,实现客户端与复杂对象之间的解耦。

    UML图如下:

     

    Client和创建对象Product之间增加工厂Factory从而实现解耦。

    一说到工厂模式,大家都会将其分为:简单工厂模式、工厂模式和抽象工厂模式,导致很多新人望而生畏。其实大可不必太纠结,它们只是实现手段和抽象层次的不同,其目的是一样的——解耦。

    • 简单工厂模式——写法最直白,在工厂中定义静态方法,根据传入的参数不同,返回不同的产品子类,新增产品时需要修改代码(增加一个条件判断)。
    • 工厂模式——为每种产品写一个对应的工厂子类,新增产品时,增加工厂子类,条件判断逻辑从Factory移到了Client,实际上依然要改代码。
    • 抽象工厂模式——抽象层次更高,工厂子类由一个变成了多个(即工厂也有了工厂,反应在类图上就是Client和Factory之间又增加一层FactoryProducer),每一个子工厂负责生产一系列相关子产品组,所有产品组组成一个产品族。

    并不是说抽象工厂模式就比工厂模式高级,区别只是适用场景不同,抽象工厂模式能处理产品种类更加复杂的情况。如果将抽象工厂模式的工厂子类减少到只剩一个,也就变成了工厂模式。


    二、应用实战

    Android系统应用有很多地方用到工厂模式,而且Android对设计模式的用法不是我们经常用到的标准写法,而是灵活运用。这也说明学设计模式学的是核心思想,而不应局限于实现方法。

    以下是Android对工厂模式的用法:

    /**
     * The factory of concrete presenters.
     */
    public class PresenterFactory {
        private static final String TAG = "PresenterFactory";
        private static final String PRESENTER_PACKAGE = "com.android.mms.ui.";
    
        //静态工厂方法,className可理解为依赖参数
        public static Presenter getPresenter(String className, Context context,
                ViewInterface view, Model model) {
            try {
                if (className.indexOf(".") == -1) {
                    className = PRESENTER_PACKAGE + className;
                }
    
           /*根据类名不同调用其构造方法生成实例*/
                Class c = Class.forName(className);
                Constructor constructor = c.getConstructor(
                        Context.class, ViewInterface.class, Model.class);
                return (Presenter) constructor.newInstance(context, view, model);
            } catch (ClassNotFoundException e) {
                Log.e(TAG, "Type not found: " + className, e);
            } catch (NoSuchMethodException e) {
                // Impossible to reach here.
                Log.e(TAG, "No such constructor.", e);
            } catch (InvocationTargetException e) {
                Log.e(TAG, "Unexpected InvocationTargetException", e);
            } catch (IllegalAccessException e) {
                Log.e(TAG, "Unexpected IllegalAccessException", e);
            } catch (InstantiationException e) {
                Log.e(TAG, "Unexpected InstantiationException", e);
            }
            return null;
        }
    }

    很显然,这里采用了反射的方式来实现简单工厂模式,如此,简单工厂模式也符合“开闭原则”了,不需要在为增加产品而修改代码。


    三、总结

    总结:工厂模式是一种创建型设计模式,对客户端来讲,它是不同于new的一种新的创建对象的方法。

    用一句话总结工厂模式:

    你说个名字我就能造出来

    优点:

    • 客户端与复杂对象解耦,想创建一个对象,只要知道其名称就可以了
    • 屏蔽产品的具体实现,调用者只关心产品的接口

    缺点:

    • 产品扩展困难,除反射方式外,一般需要修改代码
    • 增加了系统复杂度
  • 相关阅读:
    黄聪:VirtualBox 安装ghost版windows XP
    黄聪:Delphi 关键字详解[整理于 "橙子" 的帖子]
    黄聪:全局变量 HInstance 到底是在什么时候赋值的?
    黄聪:演示 Rect、Bounds 生成 TRect 的区别
    黄聪:C#操作合并多个Word文档
    黄聪:C# .Net三层架构[转]
    黄聪:遗传算法实现自动组卷、随机抽题
    黄聪:SQL转换日期字段的问题——SQL中CONVERT转化函数的用法[转]
    黄聪:System 提供的编译期函数
    黄聪:语言字符集
  • 原文地址:https://www.cnblogs.com/not2/p/11064448.html
Copyright © 2011-2022 走看看