简单工厂模式,工厂方法模式,抽象工厂模式,spring的狂想

菜鸟D在项目中遇见一个比较纠结的高耦合,所以就想办法来解耦。情况是这样的:系统通过用户选择treeview控件的节点判断调用不同的处理,这些处理中某些东西又是类似的。同事的建议是采用简单工厂,耦合就耦合吧,反正treeview节点基本是不会变化的。(能偷懒就偷懒吧)

菜鸟D有些偏执,想找些方法来解耦。于是就学习了这个几种方法,虽然不一定用的上,多学一点总是好的。

首先说简单工厂,例子是一个已经二到死的计算器。

简单工厂由三种角色组成:工厂类角色(creator),抽象产品类角色(product,图中为Iproduct接口),具体产品类角色(concreteproduct,图中为Product_A…)。

代码如下:

public class Calculate
    {
        public double DValue1 { get; set; }
        public double DValue2 { get; set; }

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

    public class Add : Calculate
    {
        public override double GetResult()
        {
            return DValue1 + DValue2;
        }
    }

    public class Sub : Calculate
    {
        public override double GetResult()
        {
            return DValue1 - DValue2;
        }
    }

    public class Mul : Calculate
    {
        public override double GetResult()
        {
            return DValue1 * DValue2;
        }
    }

    public class Div : Calculate
    {
        public override double GetResult()
        {
            if (DValue2.Equals(0))
            {
                if (DValue1.Equals(0))
                {
                    return 1;
                }
                return 0;
            }
            return DValue1 / DValue2;
        }
    }

基本的代码

            #region 客户端
            Console.WriteLine("请输入第一个数");
            string v1 = Console.ReadLine();
            Console.WriteLine("请输入运算符");
            string oper = Console.ReadLine();
            Console.WriteLine("请输入第二个数");
            string v2 = Console.ReadLine();
            Calculate c = GetCalculateByOper(oper);
            c.DValue1 = Convert.ToDouble(v1);
            c.DValue2 = Convert.ToDouble(v2);
            Console.WriteLine("结果:" + c.GetResult());
            #endregion

        #region 工厂方法
        private static Calculate GetCalculateByOper(string oper)
        {
            Calculate c = new Calculate();
            switch (oper)
            {
                case "+": c = new Add();
                    break;
                case "-": c = new Sub();
                    break;
                case "*": c = new Mul();
                    break;
                case "/": c = new Div();
                    break;
            }
            return c;
        }
        #endregion    

在这个例子中没有使用抽象类,接口,而是用了虚方法(纯粹是不想在接口里定义属性,自己喜欢用什么就用什么,毕竟这不是简单工厂的核心)。简单工厂的核心是充当工厂类角色的工厂方法(起码在此例中是这样),逻辑判断中使具体产品类和工厂直接耦合了(好像类图的关系已经决定了这种耦合,但是将具体产品和客户端解耦)。如果要添加一个开方运算,首先添加开方的运算类,然后打开工厂方法进行修改。(呵呵,违反了开闭原则)

接下来再说一下工厂方法模式,类图如下:

先分析一下类图,工厂模式有了四个角色:工厂接口,工厂实现,产品接口,产品实现(其实说角色不贴切,还不如说是种类)。工厂实现和产品实现有了依赖关系,通过调用工厂实现来获取产品实现。也就是一种产品实现对应一种工厂实现。

还是那个二的要死的计算器的例子,代码如下:

    public interface IFactory
    {
        ICalculatable GetCalculatable();
    }

    public interface ICalculatable
    {
        double GetReslut(double d1, double d2);
    }

    public class Add : ICalculatable
    {
        public double GetReslut(double d1, double d2)
        {
            return d1 + d2;
        }
    }

    public class AddFactory : IFactory
    {
        public ICalculatable GetCalculatable()
        {
            return new Add();
        }
    }

    public class Sub : ICalculatable
    {
        public double GetReslut(double d1, double d2)
        {
            return d1 - d2;
        }
    }

    public class SubFactory : IFactory
    {
        public ICalculatable GetCalculatable()
        {
            return new Sub();
        }
    }

    public class Mul : ICalculatable
    {
        public double GetReslut(double d1, double d2)
        {
            return d1 * d2;
        }
    }

    public class MulFactory : IFactory
    {
        public ICalculatable GetCalculatable()
        {
            return new Mul();
        }
    }

    public class Div : ICalculatable
    {
        public double GetReslut(double d1, double d2)
        {
            if (d2.Equals(0))
            {
                if (d1.Equals(0))
                {
                    return 1;
                }
                return 0;
            }
            return d1 / d2;
        }
    }

    public class DivFactory : IFactory
    {
        public ICalculatable GetCalculatable()
        {
            return new Div();
        }
    }

基本代码

#region 逻辑判断
    public class Factory
    {
        public static IFactory GetCalculatableByOper(string oper)
        {
            IFactory factory = null;
            switch (oper)
            {
                case "+": factory = new AddFactory();
                    break;
                case "-": factory = new SubFactory();
                    break;
                case "*": factory = new MulFactory();
                    break;
                case "/": factory = new DivFactory();
                    break;
            }
            return factory == null ? null : factory;
        }
    }
#endregion

            #region 客户端
            Console.WriteLine("请输入第一个数");
            string v1 = Console.ReadLine();
            Console.WriteLine("请输入运算符");
            string oper = Console.ReadLine();
            Console.WriteLine("请输入第二个数");
            string v2 = Console.ReadLine();
            ICalculatable calculatable = Factory.GetCalculatableByOper(oper).GetCalculatable();
            Console.WriteLine("结果:" + calculatable.GetReslut(Convert.ToDouble(v1), Convert.ToDouble(v2)));
            #endregion

注意:此处的判断逻辑已经不属于工厂模式了(类图中很明确),也可以脱离客户端。虽说简单工厂也可以这样将判断逻辑脱离客户端,但是简单工厂的逻辑判断是在工厂类中的,也就依然是简单工厂模式的一部分(此处逻辑有些乱,不懂的就认真研究类图)。通常在工厂模式的客户端需要用到哪种工厂再去创建哪种工厂,而不是如例子中的使用一个判断逻辑来选择,也就是工厂模式创建工厂是通过“外部”的逻辑来确定,而模式本身是不会做判断的。(所以这个例子并不是一个合适的例子)

此时,计算器要再添加一个开方的方法,只需添加方法实现,添加工厂实现,不会对原有的代码做修改,符合了开闭原则(你当我瞎啊,你不修改判断逻辑吗?说了多少次了,判断逻辑部分不属于工厂模式。不过比简单工厂确实多写不少东西)。

工厂方法模式通常在以下两种情况中使用 :

第一,需要使用某种产品,客户端很清楚应该使用哪个具体工厂,此种情况不存在上述的判断逻辑,只需要实例化具体工厂,然后生产具体产品。

第二,需要使用某种产品,但是不想也不需要知道是哪个工厂创建,此种情况存在一定的判断逻辑,但是客户端不需要知道这个逻辑,生产方(工厂模式)是通过外部的逻辑来生产产品,这时由外部来实例化具体工厂,生产具体产品交付给客户端。

接着再来说说抽象工厂,在抽象工厂中最明显的一个特点是产品不止一类了,所以前文提到的计算机的例子就不适合使用抽象工厂模式(窃以为如此,有反对意见的欢迎提出)。

在抽象工厂在提到一个“产品族”的概念,其实在抽象工厂中最为直观的体现就是产品A接口,产品B接口甚至是产品C、D接口。类图如下,从类图中不难发现,抽象工厂模式的具体工厂角色可以生产多种产品(工厂方法模式的具体工厂只能生产一种产品,不信去看类图)。就好像东方红拖拉机厂在工厂方法模式下只能生产拖拉机,但是在抽象工厂模式下不仅能生产拖拉机,还能生产卡车(如果加一个坦克的生产线,还能生产坦克)。

此处就用比较熟悉的农场的例子,农场生产水果和蔬菜,水果分为北方水果和热带水果,蔬菜也一样,所以农场也分为北方农场和热带农场。

代码如下:

    public interface IFruit
    {
        string Show();
    }

    public interface IVeggie
    {
        string Show();
    }

    public class NFruit : IFruit
    {
        private string name;
        public string Name
        {
            get { return "北方" + name; }
            set { name = value; }
        }

        public string Show()
        {
            return Name;
        }
    }

    public class TFruit : IFruit
    {
        string name;

        public string Name
        {
            get { return "热带" + name; }
            set { name = value; }
        }

        public string Show()
        {
            return Name;
        }
    }

    public class NVeggie : IVeggie
    {
        string name;

        public string Name
        {
            get { return "北方" + name; }
            set { name = value; }
        }

        public string Show()
        {
            return Name;
        }
    }

    public class TVeggie : IVeggie
    {
        string name;

        public string Name
        {
            get { return "热带" + name; }
            set { name = value; }
        }

        public string Show()
        {
            return Name;
        }
    }

    public interface Factory
    {
        IFruit CreateFruit(string nm);
        IVeggie CreateVeggie(string nm);
    }

    public class NFactory : Factory
    {
        public IFruit CreateFruit(string nm)
        {
            return new NFruit() { Name = nm };
        }

        public IVeggie CreateVeggie(string nm)
        {
            return new NVeggie() { Name = nm };
        }
    }

    public class TFactory : Factory
    {
        public IFruit CreateFruit(string nm)
        {
            return new TFruit() { Name = nm };
        }

        public IVeggie CreateVeggie(string nm)
        {
            return new TVeggie() { Name = nm };
        }
    }

基本代码

此例的逻辑判断部分没写。从类图上看,它是不属于抽象工厂模式的,从简化客户端的角度,这个逻辑判断是可以从客户端剥离的,很显然和工厂方法模式的逻辑判断属于同一地位(有种两头受气的感觉)。

然后再简单说spring的依赖注入。在spring中需要获取一个产品(实例)如何获取?容器来提供。逻辑判断呢?可以放在客户端,也可以从客户端剥离,爱放哪放哪。容器只依赖于配置,逻辑判断不会影响容器。所以容器很好的将生产过程与客户端隔离,这就不存在耦合了。

接下来再说一下,一直不停的重复的判断逻辑。在菜鸟D 的看法里,上述几个模式的耦合都是存在于判断逻辑中的。在简单工厂中,工厂和客户端之间耦合较低,但是工厂和具体的产品类是直接耦合的。在工厂方法模式、抽象工厂模式、spring中,逻辑判断只是一个辅助,逻辑判断将生产过程和客户端隔离,大大地降低了耦合程度。所以在衡量设计模式的耦合时,就需要衡量判断逻辑在模式中作用和角色。有些耦合是很难避免的,为了避免这些耦合甚至可能会造成更多的耦合。至于开闭原则,编码过程尽量去注意,否则为以后的开发带来麻烦就不是我们想要的了。

一家之言,不值一哂,如有谬误,欢迎指正。

菜鸟D希望这篇文章对您有所帮助。

扩展参考:

三种工厂模式区别总结

http://blog.csdn.net/lingfengtengfei/article/details/12374469

spring.net的依赖注入

http://www.cnblogs.com/GoodHelper/archive/2009/10/26/SpringNET_DI.html

工厂方法模式

http://blog.csdn.net/zhengzhb/article/details/7348707

三种工厂模式

http://www.cnblogs.com/poissonnotes/archive/2010/12/01/1893871.html

时间: 2024-10-05 17:51:25

简单工厂模式,工厂方法模式,抽象工厂模式,spring的狂想的相关文章

工厂模式总结(简单工厂,工厂方法,抽象工厂)

工厂模式属于创建型模式,大致可以分为三类,简单工厂模式.工厂方法模式.抽象工厂模式. 通过两个例子讲解这三种工厂模式 示例一 简单工厂模式 首先介绍简单工厂模式,它的主要特点是需要在工厂类中做判断,从而创造相应的产品.当增加新的产品时,就需要修改工厂类.有点抽象,举个例子就明白了.有一家生产处理器核的厂家,它只有一个工厂,能够生产两种型号的处理器核.客户需要什么样的处理器核,一定要显示地告诉生产工厂.下面给出一种实现方案. 1 enum CTYPE {COREA, COREB}; 2 class

简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别

结合简单示例和UML图,讲解工厂模式简单原理. 一.引子 话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰).Bmw(宝马).Audi(奥迪)),还雇了司机为他开车.不过,爆发户坐车时总是这样:上Benz车后跟司机说"开奔驰车!",坐上Bmw后他说"开宝马车!",坐上 Audi后他说"开奥迪车!".你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的!幸运的是这种有

Java工厂模式(简单工厂、工厂方法、抽象工厂)

工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类.工厂模式的形态工厂模式主要用一下几种形态:1:简单工厂(Simple Factory).2:工厂方法(Factory Method).3:抽象工厂(Abstract Factory). 简单工厂(Simple Factory)又叫静态工厂,是工厂模式三中状态中结构最为简单的.主要有一个静态方法,用来接受参数,并根据参数来决定返回实现同一接口的不同类的实例.我们来看一个具体的例子:假设一家工厂,几生产洗衣机,有生产冰箱

总结工厂模式---简单工厂、工厂方法、抽象工厂

简单工厂 首先,我们先看一个简单工厂的例子: #coding=utf-8 class Mercedes(object): """梅赛德斯 """ def __repr__(self): return "Mercedes-Benz" class BMW(object): """宝马 """ def __repr__(self): return "BMW&quo

设计模式(Python)-简单工厂,工厂方法和抽象工厂模式

本系列文章是希望将软件项目中最常见的设计模式用通俗易懂的语言来讲解清楚,并通过Python来实现,每个设计模式都是围绕如下三个问题: 为什么?即为什么要使用这个设计模式,在使用这个模式之前存在什么样的问题? 是什么?通过Python语言来去实现这个设计模式,用于解决为什么中提到的问题. 怎么用?理解了为什么我们也就基本了解了什么情况下使用这个模式,不过在这里还是会细化使用场景,阐述模式的局限和优缺点. 这次的主角是简单工厂,工厂方法和抽象工厂模式,由于这几个模式联系紧密,有一定的相似性,所以放在

设计模式之工厂模式(简单工厂,工厂方法,抽象工厂)

设计模式6大原则:1.开闭原则:对拓展开放,对修改关闭2.单一职责原则:一个类只复杂一项职责3.里氏原则:子类可以扩展父类的功能,但不改变父类原有的功能4.依赖倒置原则:面向接口编程5.接口隔离原则:设计接口功能尽量细粒度,最小功能单元6.迪米特法则:降低耦合度(局部变量中,不要引入新的类) 这里对工厂模式做一个学习记录 这里用简单计算器来举例. 很简单,我们需要3个输入: a1 代表第一个数字 a2 代表第二数字 operator 代表运算符 这三个参数输入后得到一个输出result 1.平时

工厂模式—工厂方法与抽象工厂的战争

概述 什么是工厂方法?什么是抽象工厂? 工厂方法是指工厂生产产品,而抽象工厂是生产产品系列.例如,工厂方法是只生产运输工具比如马车.公共汽车.自行车,而抽象工厂生产轮胎.螺丝钉交通工具零件. 工厂方法模式定义了一个创建对象的接口,但由子类决定实例化的类是哪一个.工厂方法让类把实例化推迟到子类. 抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类. 简单工厂 交通工具创建者类 public interface VehicleFactory { Vehicle creat

设计模式--10、工厂方法和抽象工厂模式

[转载]Java 之工厂方法和抽象工厂模式 1. 概念 工厂方法:一抽象产品类派生出多个具体产品类:一抽象工厂类派生出多个具体工厂类:每个具体工厂类只能创建一个具体产品类的实例. 即定义一个创建对象的接口(即抽象工厂类),让其子类(具体工厂类)决定实例化哪一个类(具体产品类).“一对一”的关系. 抽象工厂:多个抽象产品类,派生出多个具体产品类:一个抽象工厂类,派生出多个具体工厂类:每个具体工厂类可创建多个具体产品类的实例. 即提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们的具体的类.

设计模式系列---简单工厂、工厂方法、抽象工厂

前言,最近看spring的源代码.发现之前没有完全弄懂(工厂方法.抽象工厂)的区别. spring中代理对象的产生,是通过代理工厂(工厂模式),首先spring中的代理是使用jdk或者cglib的代理,只要看目标类是否实现接口. public class ProxyFactory extends ProxyCreatorSupport { //createAopProxy()方法是通过AopProxyFactory获取AopProxy(JDK,CGLIB) public Object getPr

【转】设计模式:简单工厂、工厂方法、抽象工厂之小结与区别

简单工厂,工厂方法,抽象工厂都属于设计模式中的创建型模式.其主要功能都是帮助我们把对象的实例化部分抽取了出来,优化了系统的架构,并且增强了系统的扩展性. 本文是本人对这三种模式学习后的一个小结以及对他们之间的区别的理解. 简单工厂 简单工厂模式的工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例. 不修改代码的话,是无法扩展的. 工厂方法 工厂方法是针对每一种产品提供一个工厂类.通过不同的工厂实例来创建不同的产品实例. 在同一等级结构中,支持增加任意产品. 抽象工厂 抽象工厂是应