抽象工厂

先来理解一下抽象类这个概念吧,声明方法的存在而不去实现它的类被叫做抽像类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽像类,并让它指向具体子类的一个实例。不能有抽像构造函数或抽像静态方法。Abstract 类的子类为它们父类中的所有抽像方法提供实现,否则它们也是抽像类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法,也就是抽象类中的方法只能在继承它的子类中实现。

工厂模式的简单工厂模式在这里就不细说了,首先简述简单工厂的内聚性,在软件产品设计上我们力求“高内聚低耦合”,内聚:就是一个模块内各个元素彼此结合的紧密程度,高内聚就是一个模块内各个元素彼此结合的紧密程度高。耦合:就是一个软件结构内不同模块之间互连程度的度量(耦合性也叫块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差,模块间耦合的高低取决于模块间接口的复杂性,调用的方式以及传递的信息。简单工厂的耦合度是很低的,因为工厂相互独立,但是从内聚性上看,在工厂类数量很大时要实例一个工厂类就很费劲了,可能存在一堆的判断,内聚性低;其次简单工厂不能满足开闭原则,概念:OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭。大概意思就是对于一个已有的软件,如果需要扩展,应当在不需修改已有代码的基础上进行,简单工厂在增加新的工厂类时,是一定要修改代码的,最少是加一个判断。针对简单工厂的弱点,大神们探索出了抽象工厂模式,下面我来做一个简单的抽象工厂模型,大家一同学习。

题目是:现在某商场正在做促销,商品打折,衣服打4折,衣服的原价是100元,求买一件衣服多少钱?

哈哈,这是不是太简单了,简单就简单吧,有代表性就行了,现在商场里的裤子也打折了,裤子打2折,原价也是100元,求买一条裤子和一件衣服多少钱?但此时商店里面的帽子、皮包、鞋子、袜子、妹子什么的也降价了,哈哈,这下不好搞了,有点复杂了,如果我们用简单工厂的话,我们就不得不修改代码了,因为需要判断当前要买的是什么,需要实例哪个类,等东西多到让你烦的时候,你就会觉得我加进去新的东西不就行了吗,非得让我去修改原来的代码干嘛,烦死了,这就是简单工厂不能满足OCP的原则的最好例证,让我们一起把这个烦人的重复写判断的过程省掉。

以下的代码用的是c#语言,将问题拆解,商品同有两个属性是打几折和原价,为此我们建立两个抽象类分别是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace shejimoshijihe.抽象工厂
{
    /// <summary>
    /// 原价
    /// </summary>
    public abstract class yuanjia
    {
        public abstract double Calculate();
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace shejimoshijihe.抽象工厂
{
    /// <summary>
    /// 打几折
    /// </summary>
    public abstract class daze
    {
        public abstract double Calculate();
    }
}

现在我们开始建造工厂,首先是衣服的如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace shejimoshijihe.抽象工厂
{
    public class yifudaze:daze
    {
        public override double Calculate()
        {
            return  0.4;//衣服4折
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace shejimoshijihe.抽象工厂
{
    public class yifuyuanjia : yuanjia
    {
        public override double Calculate()
        {
            return 100;//衣服原价100
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace shejimoshijihe.抽象工厂
{
    public class yifuFactory:AbstractFactory
    {
        public override daze Createdaze()
        {
            return new yifudaze();
        }
        public override yuanjia Createyuanjia()
        {
            return new yifuyuanjia();
        }
    }
}

现在来建裤子工厂

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace shejimoshijihe.抽象工厂
{
    public class kuzidaze:daze
    {
        public override double Calculate()
        {
            return  0.2;//裤子2折
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace shejimoshijihe.抽象工厂
{
    class kuziyuanjia:yuanjia
    {
        public override double Calculate()
        {
            return 100;//裤子原价100
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace shejimoshijihe.抽象工厂
{
   public class kuziFactory:AbstractFactory
    {
       public override daze Createdaze()
       {
           return new kuzidaze();
       }
       public override yuanjia Createyuanjia()
       {
           return new kuziyuanjia();
       }
    }
}

从上面的两个工厂的建造来看,我们看到了一个AbstractFactory类,衣服和裤子的工厂都继承于它,可能大家也想到了它是这个抽象工厂模式的核心了,是的,如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace shejimoshijihe.抽象工厂
{
    public abstract class AbstractFactory
    {
        public abstract yuanjia Createyuanjia();

        public abstract daze Createdaze();
    }
}

此处就是抽象工厂高内聚的所在了,我们看到衣服和裤子的工厂里都有关于Createyuanjia()和Createdaze()的实现,好了,到此我们就算加再多的商品都不用担心了去修改简单工厂里if(kuzi)else if(yifu)else if(meizi)判断了,现在我们只管添加新的商品工厂就行了,问题又来了,我们怎么取代那个判断呢,我们可以利用反射原理来获得,你现在输入商品的对应的是哪个工厂,我做的是一个窗体:如下

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace shejimoshijihe.抽象工厂
{
    public partial class CHOUXIANGGCANG : Form
    {
        public CHOUXIANGGCANG()
        {
            InitializeComponent();
        }

         double num= 0;
        private void button1_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(comboBox1.Text))
            {
                Assembly assembly = Assembly.GetExecutingAssembly(); //反射获取当前程序集 
                object obj = assembly.CreateInstance("shejimoshijihe.抽象工厂." + comboBox1.Text);//comboBox1.Text的值是工厂的名,作为开发者获取他是没问题的
                AbstractFactory ab = (AbstractFactory)obj;
                //(AbstractFactory)obj.Createyuanjia().Calculate();
                //(AbstractFactory)obj.Createdaze().Calculate();
                double yfyuanjia = ab.Createyuanjia().Calculate();
                double yifudaze = ab.Createdaze().Calculate();
                double jiage = yfyuanjia * yifudaze;
                num += jiage;
                this.label1.Text ="一共"+ num.ToString();
            }
        }
    }
}

好了,我们现在算是把它搭建完毕了。剩下的事就是你需要加东西了,需要加什么你就加一个工厂就行了,抽象工厂解决了简单工厂的内聚问题,同时增加了可扩展性,当然简单工厂在一般情况下还是很好用的,不如业务不多的时候,代码会很清晰易懂。博主不善于画图,逻辑结构图可到网上查阅。

原文地址:https://www.cnblogs.com/ouzining/p/4174495.html