• 设计模式-简单工厂模式


    模式定义

    简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式定义了一个创建对象的类,由这个类来封装实例化对象的行为。

    设计原则

    遵循的原则:

    • 依赖倒置原则
    • 迪米特法则
    • 里氏替换原则
    • 接口隔离原则

    未遵循的原则

    • 开闭原则
    • 单一职责原则

    UML类图

    简单工厂模式类图

    简单工厂模式实例

    问题描述

    Pizza 类有很多子类,要求根据不同的情况用不同的子类实例化一个 Pizza 对象。

    首先我们定义披萨接口

    package com.wpx.simplefactory;
    
    /**
     * 定义披萨接口
     */
    public interface Pizza {
        public void make();
    }
    
    

    接着,定义两个具体的披萨类,乳酪比萨和希腊披萨

    package com.wpx.simplefactory;
    
    /**
     * 具体的披萨-乳酪比萨
     */
    public class CheesePizza implements Pizza {
    
        @Override
        public void make() {
            System.out.println("乳酪比萨");
        }
    }
    
    
    package com.wpx.simplefactory;
    
    /**
     * 具体的披萨-希腊披萨
     */
    public class GreekPizza implements Pizza {
    
        @Override
        public void make() {
            System.out.println("希腊披萨");
    
        }
    }
    

    紧接着,我们定义一个披萨工厂来生产披萨

    package com.wpx.simplefactory;
    
    /**
     * 披萨工厂类
     */
    public class SimplePizzaFactory {
        public static Pizza createPizza(String type) {
            if (type.equals("乳酪比萨")) {
                return new CheesePizza();
            } else if (type.equals("希腊披萨")) {
                return new GreekPizza();
            } else {
                throw new UnsupportedOperationException();
            }
        }
    }
    

    现在一个基于简单工厂模式的披萨工厂就建造完成了,我们对此进行测试,让披萨工厂来一份乳酪披萨尝尝。

    package com.wpx.simplefactory;
    
    /**
     * 测试简单工厂模式-披萨工厂
     */
    public class PizzaStore {
        public static void main(String[] args) {
            Pizza pizza = SimplePizzaFactory.createPizza("乳酪比萨");
            pizza.make();
        }
    }
    

    运行结果

    乳酪比萨
    
    Process finished with exit code 0
    

    java.text.DateFormat中的简单工厂模式

    DateFormat:jdk中的一个工具类java.text.DateFormat,用来格式化一个本地日期与时间

    通过源码我们可以知道DateFormat是一个抽象类(abstract),下面的源代码就是这个类里包含的方法,其实这些就是静态工厂方法,通过静态方法来提供自己的实例是完全可以的(抽象类本身不能进行实例化)。从源码可以看出getDateInstance()方法做了两件事情:

    1. 运用了多态性:由于SimpleDateFormat是DateFormat的子类,而getDateInstance()声明的类型为DateFormat而实际返回类型为子类SimpleDateFormat
    2. 使用了静态工厂方法(static):由于DateFormat是抽象类不能进行实例化,因此也就不能调用其中的普通方法(非静态方法)。因此我们必须将其声明为static,才能返回实例

    通过上面做的两件事情就将具体子类的实例化过程隐藏起来了,调用者不必考虑具体子类的实例化,因为抽象类会提供它的合适子类实例

        public final static DateFormat getDateInstance()
        {
            return get(0, DEFAULT, 2, Locale.getDefault());
        }
    
        public final static DateFormat getDateInstance(int style)
        {
            return get(0, style, 2, Locale.getDefault());
        }
    
        public final static DateFormat getDateInstance(int style,
                                                     Locale aLocale)
        {
            return get(0, style, 2, aLocale);
        }
        
        private static DateFormat get(int timeStyle, int dateStyle,
                                      int flags, Locale loc) {
            if ((flags & 1) != 0) {
                if (timeStyle < 0 || timeStyle > 3) {
                    throw new IllegalArgumentException("Illegal time style " + timeStyle);
                }
            } else {
                timeStyle = -1;
            }
            if ((flags & 2) != 0) {
                if (dateStyle < 0 || dateStyle > 3) {
                    throw new IllegalArgumentException("Illegal date style " + dateStyle);
                }
            } else {
                dateStyle = -1;
            }
            try {
                // Check whether a provider can provide an implementation that's closer 
                // to the requested locale than what the Java runtime itself can provide.
                LocaleServiceProviderPool pool =
                    LocaleServiceProviderPool.getPool(DateFormatProvider.class);
                if (pool.hasProviders()) {
                    DateFormat providersInstance = pool.getLocalizedObject(
                                                        DateFormatGetter.INSTANCE,
                                                        loc, 
                                                        timeStyle,
                                                        dateStyle,
                                                        flags);
                    if (providersInstance != null) {
                        return providersInstance;
                    }
                }
    
                return new SimpleDateFormat(timeStyle, dateStyle, loc);
            } catch (MissingResourceException e) {
                return new SimpleDateFormat("M/d/yy h:mm a");
            }
        }
    

    总结

    优点:

    • 将创建实例的工作与使用实例的工作分开,使用者不必关心类对象如何创建,明确了职责。
    • 把初始化实例时的工作放到工厂里进行,使代码更容易维护。更符合面向对象的原则,面向接口编程,而不是面向实现编程。

    缺点:

    • 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
    • 要新增产品类的时候,就要修改工厂类的代码,违反了开放封闭原则(对扩展的开放,对修改的关闭)。
    • 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
  • 相关阅读:
    Java最近版本新特性使用介绍
    Android开发指南-框架主题-安全和许可
    Android启动组件的三种主流及若干非主流方式
    Android自定义权限和使用权限
    Android 安全架构及权限控制机制剖析
    物联网操作系统Hello China V1.76(PC串口版)版本发布
    android 点九PNG技术 适应不同分辨率 完美显示效果
    mysl lock table read
    mysl lock table read
    mysql DBI 事务控制
  • 原文地址:https://www.cnblogs.com/wupeixuan/p/8645734.html
Copyright © 2020-2023  润新知