• 案例分析:设计模式与代码的结构特性——工厂方法模式


    什么是工厂方法模式

      工厂方法模式(FACTORY METHOD)是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽象工厂;具体工厂;抽象产品;具体产品。工厂方法(Factory Method)模式定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

      工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。

    工厂方法模式的特点

    工厂方法模式优点
    (1)在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无需知道具体产品类的类名。
    (2)基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,正是因为所有的具体工厂类都具有同一抽象父类。
    (3)使用工厂方法模式的另一个优点是在系统中加入新产品时无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,只需要添加一个具体工厂和具体产品即可,这样系统的可扩展性也就变得非常好,完全符合开闭原则。


    工厂方法模式缺点
    (1)在添加新产品时需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
    (2)由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度。


    工厂方法模式适用环境
    (1)客户端不知道它所需要的对象的类。在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体产品对象由具体工厂类创建,可将具体工厂类的类名存储在配置文件或数据库中。
    (2)抽象工厂类通过其子类来指定创建哪个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时子类对象将覆盖父类对象,从而使得系统更容易扩展。

    工厂方法模式的结构

    UML类图

    成员组成

    组成(角色)关系作用
    抽象产品 具体产品的父类 描述具体产品的公共接口
    具体产品 抽象产品的子类;工厂类创建的目标类 描述生产的具体产品
    抽象工厂 具体工厂的父类 描述具体工厂的公共接口
    具体工厂 抽象工厂的子类;被外界调用 描述具体工厂;实现FactoryMethod工厂方法创建产品的实例
    工厂方法模式的具体实现
    背景:现在有一个运算器只能进行加法运算,现在有不同的客户需要不同的运算,如乘法,减法,除法等等,如果重新构造乘法运算器、除法运算器、减法运算器无疑使代码太过于松散而且冗杂,现在引入工厂方法模式,在原有的运算工厂下开发出新的计算方法。
     
    UML图
     
     
    关键代码:
    计算器工厂:
    /*
     * 工厂接口
     */
    interface Calculator {
        Operation createOperation();
    }
     
    

      

    加法工厂:
    /*
     * 加法操作工厂
     */
    class Addop implements Calculator {
        public Operation createOperation() {
            return new OperationAdd();
        }
    }
    

      

    减法工厂:
    /*
     * 减法操作工厂
     */
    class Minusop implements Calculator {
        public Operation createOperation() {
            return new OperationMinus();
        }
    }
     
    

      

    乘法工厂:
    /*
     * 乘法操作工厂
     */
    class Multiop implements Calculator {
        public Operation createOperation() {
            return new OperationMul();
        }
    }
    

      

    除法工厂:
    /*
     * 除法操作工厂
     */
    class Divop implements Calculator {
        public Operation createOperation() {
            return new OperationDiv();
        }
    }
    

      

    操作接口:
    abstract class Operation {
        public abstract int getResult(int a, int b);
    }
    

      

    加法操作:
    /*
     * 加法操作
     */
    class OperationAdd extends Operation {
        public int getResult(int a, int b) {
            return a + b;
        }
    }
    

      

    减法操作:
    /*
     * 减法操作
     */
    class OperationMinus extends Operation {
        public int getResult(int a, int b) {
            return a - b;
        }
    }
     
    

      

    乘法操作:
    /*
     * 乘法操作
     */
    class OperationMul extends Operation {
        public int getResult(int a, int b) {
            return a * b;
        }
    }
    

      

    除法操作:
    /*
     * 除法操作
     */
    class OperationDiv extends Operation {
        public int getResult(int a, int b) {
            return a / b;
        }
    }
     
    

      

    完整代码:
  • 相关阅读:
    CSS实现雨滴动画效果
    大型网站架构系列:电商网站架构案例
    CSS 不定宽高的垂直水平居中方式总汇
    js中尺寸类样式
    Tiling
    排序二叉树
    算术表达式的转换
    Area
    catch that cow
    R中双表操作学习[转载]
  • 原文地址:https://www.cnblogs.com/Liwj57csseblog/p/12001747.html
Copyright © 2020-2023  润新知