• 设计模式01之 简单工厂模式(创建模式)


    概要

    本章介绍"简单工厂模式"。内容包括:
    简单工厂模式简介
    简单工厂模式代码模型
    简单工厂模式示例

    说明:(01) 本文是在《Java与模式》的学习总结文章! (02) 文章中的UML的相关内容(包括类图说明绘图工具等),可以参考"UML系列" 文章。

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3526186.html

    简单工厂模式简介

    简单工厂模式(Simple Factory),又被称为"静态工厂方法模式"。它属于"创建模式"(创建对象的模式),并且是"工厂方法"模式的一种特殊实现。
    通常,我们利用简单工厂模式来进行类的创建。例如,获取线程池对象,就是通过简单工厂模式来实现的。它的结构图如下所示:

    简单工厂模式的结构共包括3个组成部分:工厂(Factory)抽象产品(Product)具体产品(ConcreteProduct)

    1. 工厂 -- 工厂是简单工厂模式的核心,提供了对外接口。客户端或其它程序要获取Product对象,都是通过Factory的接口来获取的。

    2. 抽象产品 -- 抽象产品是(许多)不同产品抽象出来的。Product可以是接口或者抽象类。

    3. 具体产品 -- 工厂中返回的产品对象,实际上是通过ConcreteProduct来创建的。

    简单工厂模式代码模型

    public class Factory {
        public static Product newInstance() {
            return new ConcreteProduct();
        }
    }
    public abstract Product {
    }
    public class ConcreteProduct extends Product {
        public ConcreteProduct() {}
    }

    模型的类图

     

    简单工厂模式示例

    假设现在有一个水果工厂,能够生成各种各样的水果。目前能生产的水果包括苹果,葡萄和草莓。
    我们通过"简单工厂模式"描述该问题,它的UML类图如下:

    1. 工厂类
    工厂类是"FruitFactory"。FruitFactory是水果工厂,水果工厂会生成水果。
    FruitFactory的源码

     1 public class FruitFactory {
     2 
     3     public static Fruit newInstance(String name) 
     4         throws BadFruitException {
     5         // 如果name等于"apple"(忽略大小写),则返回苹果。
     6         if ("apple".equalsIgnoreCase(name)) {
     7             return new Apple();
     8         // 如果name等于"grape"(忽略大小写),则返回葡萄。
     9         } else if ("grape".equalsIgnoreCase(name)) {
    10             return new Grape();
    11         // 如果name等于"strawberry"(忽略大小写),则返回草莓。
    12         } else if ("strawberry".equalsIgnoreCase(name)) {
    13             return new Strawberry();
    14         // 其它情况,则抛出异常。
    15         } else {
    16             throw new BadFruitException("Bad fruit request!");
    17         }
    18     }
    19 }

    2. 抽象产品类
    Product类是"Fruit"。Fruit代表水果,它是抽象类,包含水果的基本特征:生长,种植,收获。
    Fruit的源码

    1 public abstract class Fruit {
    2     abstract void grow();    // 生长
    3     abstract void harvest(); // 收获
    4     abstract void plant();   // 种植
    5 }

    3. 具体产品类
    具体产品类是"Apple", "Grape"和"Strawberry"。它们是3种具体的水果,分别代表苹果,葡萄和草莓。
    Apple的源码

     1 // Apple实现Fruit的函数接口,并且Apple中有私有成员age和私有方法log。
     2 public class Apple extends Fruit {
     3     private int age;
     4 
     5     public void grow() {
     6         log("Apple grow()");
     7     }
     8     public void harvest() {
     9         log("Apple harvest()");
    10     }
    11     public void plant() {
    12         log("Apple plant()");
    13     }
    14     public void setAge(int age) {
    15         this.age = age;
    16     }
    17     public int getAge() {
    18         return age;
    19     }
    20     private void log(String msg) {
    21         System.out.println(msg);
    22     }
    23 }

    Grape的源码

     1 // Grape仅仅只实现Fruit的函数接口。
     2 public class Grape extends Fruit {
     3     public void grow() {
     4         System.out.println("Grape grow()");
     5     }
     6     public void harvest() {
     7         System.out.println("Grape harvest()");
     8     }
     9     public void plant() {
    10         System.out.println("Grape plant()");
    11     }
    12 }

    Strawberry的源码

     1 // Strawberry实现Fruit的函数接口,并且Strawberry中有私有方法log
     2 public class Strawberry extends Fruit {
     3 
     4     public void grow() {
     5         log("Strawberry grow()");
     6     }
     7     public void harvest() {
     8         log("Strawberry harvest()");
     9     }
    10     public void plant() {
    11         log("Strawberry plant()");
    12     }
    13     private void log(String msg) {
    14         System.out.println(msg);
    15     }
    16 }

    4. 客户端测试程序
    客户端是"Client"。
    Client的源码

     1 public class Client {
     2 
     3     public static void main(String[] args) {
     4         try {
     5             Fruit apple = FruitFactory.newInstance("Apple");
     6             apple.plant();
     7             apple.grow();
     8             apple.harvest();
     9 
    10             Fruit grape = FruitFactory.newInstance("Grape");
    11             grape.plant();
    12             grape.grow();
    13             grape.harvest();
    14 
    15             Fruit strawberry = FruitFactory.newInstance("strawberry");
    16             strawberry.plant();
    17             strawberry.grow();
    18             strawberry.harvest();
    19 
    20             Fruit error = FruitFactory.newInstance("error");
    21             error.plant();
    22             error.grow();
    23             error.harvest();
    24         } catch (BadFruitException e) {
    25             e.printStackTrace();
    26         }
    27     }
    28 }

    运行结果

    Apple plant()
    Apple grow()
    Apple harvest()
    Grape plant()
    Grape grow()
    Grape harvest()
    Strawberry plant()
    Strawberry grow()
    Strawberry harvest()
    BadFruitException: Bad fruit request!
        at FruitFactory.newInstance(FruitFactory.java:17)
        at Client.main(Client.java:21)

    结果说明

    Client成功创建了Apple, Grape, Strawberry这3个水果对象,并调用了它们的方法;然后创建error时,由于不存在error对应的水果,因此抛出异常。
    (01) Fruit,是抽象产品。Fruit中声明了grow(), harvest(), plant()这3个函数接口,它们是水果共用拥有的行为。
    (02) Apple, Grape和Strawberry这三个类是具体产品。
          Apple -- 实现Fruit的函数接口,并且Apple中有私有成员age和私有方法log。
          Grape -- 仅仅只实现Fruit的函数接口。
          Strawberry -- 实现Fruit的函数接口,并且Strawberry中有私有方法log
    (03) FruitFactory,是工厂类。通过它的newInstance()方法,我们可以获取相应的Fruit对象。若要获取的水果不存在,则抛出BadFruitException异常。BadFruitException是Exception的子类。

  • 相关阅读:
    看动画学算法之:排序-归并排序
    看动画学算法之:排序-选择排序
    【电脑】第3期:电脑如何打开上帝模式?
    限时删除!能挑战idm的下片神器,最快33M/S
    基本类型计算中浮点数的错误
    字符数组的toString方法打印的是地址值
    boolean类型的成员变量自动生成get方法的问题
    多态的使用
    抽象类和接口的使用关系
    接口的注意事项
  • 原文地址:https://www.cnblogs.com/skywang12345/p/3526186.html
Copyright © 2020-2023  润新知