xml地图|网站地图|网站标签 [设为首页] [加入收藏]

设计模式,JAVA简单工厂模式总结

慢慢的做记录,做最强大的自己

  简单工厂模式(Factory Pattern)是一种创建型的设计模式,像工厂一样根据要求生产对象实例。

大二结束了java和java web的基础课程,大三开始自学各种框架,在看书和观看视频过程中发现自己设计模式知识的欠缺,使得自己学习的时候云里雾里,知其然不知其所以然,在某一篇博文中看到“框架是软件,而设计模式是软件的知识”,所以决定自己再扎实的学一遍设计模式,并且写下自己总结的文章,各种繁杂的定义就不写了,网上和书上一大堆,希望自己可以写的偏实际一点。(由于第一次写文章,水平有限,若有错误希望大家指正)

看了大话设计模式之后感触很深,发现自己还有很多学习的东西,设计软件并不是一两句代码把功能写完了就行,需要思考的内容有很多

  特点:根据不同的条件,工厂实例化出合适的对象。

其实这也是初学设计模式时经常会想到的问题,网上给的例子一般都太简单,虽然能够说明实现方式和原理,可总给人一种为了使用而使用的感觉,绕来绕去我还不如自己new一个对象

代码来源参考大话设计模式这本书,这里在博客里记录一下,不可能每次都去翻书,但是在博客里面是非常好找的。

  《大话设计模式》中实例:四则运算计算器

首先,工厂模式是为了解耦,“高内聚、低耦合”是所有软件设计者所追求的,很多设计模式也都是为了这个目的而存在。接下来我会用很大篇幅的代码一步一步的引出为什么需要简单工厂模式

范例为一个简单工厂模式的计算器,首先先创建一个计算器运算所需要用到的数据模型,在java里面也叫bean,就是一个抽象的类,这里我们先创建一个Operation类

  代码:

必威,在《大话设计模式》有一个写简单计算器的例子如下

public class Operation
    {
        private double _numberA = 0;
        private double _numberB = 0;

        public double NumberA
        {
            get { return _numberA; }
            set { _numberA = value; }
        }

        public double NumberB
        {
            get { return _numberB; }
            set { _numberB = value; }
        }

        public virtual double GetResult()
        {
            double results = 0;
            return results;
        }



    }
 1 #!/usr/bin/env python
 2 #-*- coding: utf-8 -*-
 3 
 4 class Operation:
 5     def getResult(self):
 6         pass
 7 
 8 class OperationAdd(Operation):
 9     def getResult(self):
10         return self.op1+self.op2
11 
12 class OperationSub(Operation):
13     def getResult(self):
14         return self.op1-self.op2
15     
16 class OperationMul(Operation):
17     def getResult(slef):
18         return self.op1*self.op2
19 
20 class OperationDiv(Operation):
21     def getResult(self):
22         try:
23             return self.op1/float(self.op2)
24         except:
25             print("Error:除数为0!")
26             return 0
27 
28 class OperationOther(Operation):
29     def getResult(self):
30         print("Error:没有定义的运算符!")
31         return 0
32     
33 
34 class OperationFactory:
35     
36     operation = {}
37     operation["+"] = OperationAdd()
38     operation["-"] = OperationSub()
39     operation["*"] = OperationMul()
40     operation["/"] = OperationDiv()
41     
42     def createOperation(self,choice):
43         if choice in self.operation.keys():
44             op = self.operation[choice]
45         else:
46             op = OperationOther()
47         return op
48 
49 
50 
51 if __name__ == "__main__":
52     op = raw_input("请输入运算符:")
53     num_a = input("a:")
54     num_b = input("b:")
55 
56     factory = OperationFactory()
57     cal = factory.createOperation(op)
58 
59     cal.op1 = num_a
60     cal.op2 = num_b
61     
62     print(u"运算结果为:" + str(cal.getResult()))
63 
public class Calculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println; Double numberA = scanner.nextDouble(); System.out.println("请输入运算符号"); scanner.nextLine();//吃一个换行符 String operator = scanner.nextLine(); System.out.println; Double numberB = scanner.nextDouble(); Double result; switch  { case "+": result = numberA + numberB; break; case "-": result = numberA - numberB; break; case "*": result = numberA * numberB; break; case "/": try { result = numberA / numberB; } catch (ArithmeticException e) { System.out.println; return; } break; default: System.out.println("没有该运算规则"); return; } System.out.println("结果是:"+result); }}

然后再创建加减乘除类,以便工厂进行调用

  

这是初学者在学习java时最容易写出的代码,特别是刚刚学习C语言过后,我们来看一看上面的代码在设计上存在哪些问题

class OperationAdd : Operation
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA + NumberB;
            return result;
        }
    }

    class OperationSub : Operation
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA - NumberB;
            return result;
        }
    }

    class OperationMul : Operation
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA * NumberB;
            return result;
        }
    }

    class OperationDiv : Operation
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA / NumberB;
            return result;
        }
    }

  当需要使用到单个实体的多个变体时,可以使用工厂模式。例如上面的例子中,需要做运算(单个实体),然而常用的运算包括加、减、乘、除(变体),不同的条件下需要创建不同的变体,这时就可以通过工厂来创建不同的运算。

没有使用到面向对象的思想

如果现在我们的身边有一个计算器,大家想一想它会是什么样的,首先我们会看到屏幕和各种按键,当正确的按下一系列按键后,我们会在屏幕上看到结果,可后面的具体运算过程我们是看不到的。接下来看上面的代码,输出打印语句类比为屏幕,输入语句是按键,剩下的case switch 定义变量等语句都是计算过程,而这些计算过程都是可以隐藏起来的,这样界面和业务逻辑完全分离,降低耦合性,便于程序维护。

修改过后代码如下

public class View { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println; Double numberA = scanner.nextDouble(); System.out.println("请输入运算符号"); scanner.nextLine();//吃一个换行符 String operator = scanner.nextLine(); System.out.println; Double numberB = scanner.nextDouble(); Double result = null; try { result = Calculator.calculator(numberA,operator,numberB); System.out.println("结果是:"+result); } catch (Exception e) { e.printStackTrace(); } }}

public class Calculator { public static Double calculator(Double numberA,String operator,Double numberB) throws ArithmeticException{ double result; switch  { case "+": result = numberA + numberB; break; case "-": result = numberA - numberB; break; case "*": result = numberA * numberB; break; case "/": try { result = numberA / numberB; } catch (ArithmeticException e) { throw new ArithmeticException("被除数不能为0"); } break; default: throw new ArithmeticException("没有这个运算规则"); } return result; }}

这样就分离了业务逻辑和界面,但我们再看看这样的代码还有什么问题

创建工厂类,实例化出合适的对象

  步骤:

扩展性极差

如果有一天我们需要加上开方、平方等运算,所有的加减乘除等功能都得参与程序的编译,在增加功能的同时还有误修改源码的风险,违背开放闭合原则。

继续修改代码

abstract public class Operation { private double a; private double b; abstract public double getResult() throws Exception; //定义一个抽象类 其中有一个运算抽象方法 public double getA() { return a; } public void setA { this.a = a; } public double getB() { return b; } public void setB { this.b = b; }}

public class AddOperation extends Operation{ @Override public double getResult() { double result=super.getA()+super.getB(); return result; }}

public class SubOperation extends Operation{ @Override public double getResult() { double result=super.getA()-super.getB(); return result; }}

public class MulOperation extends Operation { @Override public double getResult() { double result=super.getA()*super.getB(); return result; }}

public class SubOperation extends Operation{ @Override public double getResult() { double result=super.getA()-super.getB(); return result; }}

修改后的代码扩展性大大增强,当我们需要增加其他运算时,我们只需要让新类继承Operation类并实现getResult方法,不需要去修改其他功能模块的代码。可新问题来了,在运算的时候,我们需要有选择性的实例化某一个对象,这个时候就用到了简单工厂模式。

虽然我真的特别特别特别的不喜欢那些臃肿的定义,不过在某些角度看来,为了让知识系统化,了解一些定义还是挺有必要的。不过在上定义之前,咱们先看看模式的结构

简单工厂模式包含如下角色:Factory:工厂角色Product:抽象产品角色ConcreteProduct:具体产品角色

工厂角色是简单工厂模式的核心,它负责实现创建所有具体产品类的实例。工厂类可以被外界直接调用,创建所需的产品对象。(也就是我们在后面的OperationFactory类)

抽象产品角色是所有具体产品角色的父类,它负责描述所有实例所共有的公共接口。(上面代码的Operation类)

具体产品角色(Concrete Product)继承自抽象产品角色,一般为多个,是简单工厂模式的创建目标。工厂类返回的都是该角色的某一具体产品。(Operation的子类)

补齐后面的代码

public class OperationFactory { public static Operation createOperation throws Exception{ switch  { case '+': return new AddOperation(); case '-': return new SubOperation(); case '*': return new MulOperation(); case '/': return new DivOperation(); default: throw new Exception; } }}

public class Main { public static void main(String[] args) { Operation opr = null; double a; char op; double b; Scanner sc = new Scanner(System.in); a = sc.nextDouble(); op = sc.next().charAt; b = sc.nextDouble(); try { opr=OperationFactory.createOperation; opr.setA; opr.setB; System.out.println(opr.getResult; }catch (Exception e) { System.out.println(e.getMessage; } }}

简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数(也就是上述的各种运算符号)的不同返回不同类的实例(上述的运算方法子类)。简单工厂模式专门定义一个类(上述的OperationFactory类)来负责创建其他类的实例,被创建的实例通常都具有共同的父类(上述的Operation类)。

简单工厂模式无非是对面向对象思想的一种体现,我需要什么,你就给我提供什么,通过继承和多态又将业务逻辑中的代码解耦,使得各个功能之间耦合度降低,便于程序扩展维护,当然有人会说,在增加新功能以后,我们依旧需要去修改工厂类的switch语句,这个问题就通过以后在写抽象工厂模式的总结的时候解答吧。

 public static Operation CreateOperate(string operate)
        {
            Operation oper = null;
            switch (operate)
            {
                case "+":
                    oper = new OperationAdd();
                    break;
                case "-":
                    oper = new OperationSub();
                    break;
                case "*":
                    oper = new OperationMul();
                    break;
                case "/":
                    oper = new OperationDiv();
                    break;

            }
            return oper;
        }
  • 创建实体类

    class Entity(): #实体

    def Func(self):
        "方法体"
    

         #pass

  • 创建变体类

    class Variant1(Entity):

    def Func(self):
    

         pass

 

class Variant2(Entity):
    def Func(self):
     pass

通过多态,返回父类的方式,然后实现计算结果

 

static void Main(string[] args)
        {
            Operation oper;
            oper = OperationFactory.CreateOperate("+");
            oper.NumberA = 1;
            oper.NumberB = 2;
            double result = oper.GetResult();
            Console.WriteLine(result);
            Console.ReadLine();
        }
  • 创建工厂类

    class EntityFactory():

    def create_variant(self,choice):
        #根据choice创建不同的variant类
        #函数体
        #return
    

但是简单工厂模式会存在一个问题,后续如果新增方法的话那么还需要继续创建运算类,然后实例化对象,那么这样会增加代码结构的复杂度,当然还是有方法解决的,但是这里就只做简单工厂模式的介绍了,

 

三层模型基本上如果不是用了特别的方法那么基本都是基于简单工厂模式来处理方法的

  使用工厂类:

  

factory  = EntityFactory()
variant = factory.create_variant(choice)
print(variant.Func())

 

本文由必威发布于编程,转载请注明出处:设计模式,JAVA简单工厂模式总结