首页 > 代码库 > 抽象工厂
抽象工厂
先来理解一下抽象类这个概念吧,声明方法的存在而不去实现它的类被叫做抽像类(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(); } } }}
好了,我们现在算是把它搭建完毕了。剩下的事就是你需要加东西了,需要加什么你就加一个工厂就行了,抽象工厂解决了简单工厂的内聚问题,同时增加了可扩展性,当然简单工厂在一般情况下还是很好用的,不如业务不多的时候,代码会很清晰易懂。博主不善于画图,逻辑结构图可到网上查阅。
抽象工厂