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

      简单工厂模式(静态工厂方法模式)就是由一个工厂类根据传入的参量决定创建出哪一种产品类的实例。其结构如下图所示:

            

      简单工厂模式涉及到工厂角色、抽象产品角色和具体产品角色。

          (1)工厂类(Creator)角色:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,镪往往由一个具体Java类实现。

          (2)抽象产品(Product)角色:担任这个角色的类是由工厂方法模式所创建的对象的父类,或它们共同拥有的接口。抽象产品角色可以用一个Java接口或者Java抽象类实现。

       (3)具体产品(ConcreteProduct)角色:工厂方法模式所创建的任何对象都是这个角色的实例,具体产品角色由一个具体Java类实现。 

    源代码:

          抽象产品(Product)接口

    public interface Product {
    }

      具体产品(ConcreteProduct)类

    public class ConcreteProduct implements Product{
        public ConcreteProduct(){
    
        }
    }

      工厂类(Creator)

    public class Creator {
        public static Product factory(){
            return new ConcreteProduct();
        }
    }

    最后我们来看个例子:

           比如有一个农场公司,专门向市场销售各类水果:葡萄(Grape)、草莓(Strawberry)、苹果(Apple)。水果(Fruit)接口规定所有水果必须实现的接口,包括任何水果类必须具备的方法: 种植plant(),生长grow(),收获harvest()。

      Fruit接口

    public interface Fruit {
        void grow();
        void harvest();
        void plant();
    }

         Apple类

    public class Apple implements Fruit
    {
    
        public void grow()
        {
            System.out.println("Apple is growing...");
        }
    
        public void harvest()
        {
            System.out.println("Apple has been harvested.");
        }
    
        public void plant()
        {
            System.out.println("Apple has been planted.");
        }
    
        public int getTreeAge(){ return treeAge; }
    
        public void setTreeAge(int treeAge){ this.treeAge = treeAge; }
    
        private int treeAge;
    }

      Grape类

    public class Grape implements Fruit
    {
        public void grow()
        {
            System.out.println("Grape is growing...");
        }
    
        public void harvest()
        {
            System.out.println("Grape has been harvested.");
        }
    
        public void plant()
        {
            System.out.println("Grape has been planted.");
        }
    
        public boolean getSeedless()
        {
            return seedless;
        }
    
        public void setSeedless(boolean seedless)
        {
            this.seedless = seedless;
        }
    
        private boolean seedless;
    }

      Strawberry类

    public class Strawberry implements Fruit
    {
        
        public void grow()
        {
            System.out.println("Strawberry is growing...");
        }
    
        public void harvest()
        {
            System.out.println("Strawberry has been harvested.");
        }
    
        public void plant()
        {
            System.out.println("Strawberry has been planted.");
        }
    
    }

      FruitFactory类

    public class FruitFactory
    {
        public static Fruit factory(String which) throws BadFruitException
        {
            if (which.equalsIgnoreCase("apple"))
            {
                return new Apple();
            }
            else if (which.equalsIgnoreCase("strawberry"))
            {
                return new Strawberry();
            }
            else if (which.equalsIgnoreCase("grape"))
            {
                return new Grape();
            }
            else
            {
                 throw new BadFruitException("Bad fruit request");
            }
        }
    }

      简单工厂模式的优点:

       简单工厂模式的核心是工厂类,这个类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,而客户端则可以免除直接创建产品对象的责任,而仅仅负责“消费”产品,简单工厂模式通过这种做法实现 了对责任的分割。

      简单工厂模式的缺点:

      (1)工厂类集中了所有的产品创建逻辑,形成一个无所不知的全能类,它什么时候不工作了,影响很大。

      (2)当产品类有不同的接口种类时,工厂类需要判断在什么时候创建某种产品。这种对时机的判断和对哪一种具体产品的判断逻辑混合在一起,使得系统在将来进行功能扩展较为困难。

      (3)由于简单工厂模式使用静态方法作为工厂方法,而静态方法无法由子类继承,因此工厂角色无法形成基于继承的等级结构。

      简单工厂方法与开闭原则:

       开闭原则要求一个 系统的设计能够允许系统在无须修改的情况下,扩展其功能。

      对于产品消费角色来说,任何时候需要某种产品,只需向工厂角色请求即可。而工厂角色在接到请求后,会自行判断创建和提供哪一个产品。所以,产品消费角色无需知道它得到的是哪一个产品;换言之,产品消费角色无需修改就可以接纳新的产品。

      对于工厂角色而言,增加 新产品是一个痛苦的过程。工厂角色必须知道每一种产品,如何创建它们,以及何时向客户端提供它们。换言之,接纳新的产品意味着修改这个工厂角色的源码。

      开闭原则要求系统允许当新的产品加入系统中时,而无需对现有代码进行修改。这一点对于产品的消费角色是成立的,而对于工厂角色是不成立的。

      综上,简单工厂模式只在有限的程度上支持“开闭”原则。

  • 相关阅读:
    Tarjan在图论中的应用(三)——用Tarjan来求解2-SAT
    【CodeForces】CodeForcesRound594 Div1 解题报告
    JS面向对象组件(三)--面向对象中的常用属性和方法
    JS面向对象组件(二)--Javascript原型链
    JS面向对象组件(一) ---包装对象与原型链
    JS面向对象组件(六) -- 拖拽功能以及组件的延展
    面试题目
    webstorm安装破解版
    面试题整理
    Javascript模块化编程(三):require.js的用法 (转)
  • 原文地址:https://www.cnblogs.com/flythinking/p/7221191.html
Copyright © 2011-2022 走看看