一、概念
简单工厂模式(Simple Factory Pattern)属于创建型模式,又叫做静态工厂方法模式(Static FactoryMethod Pattern),可是不属于23GOF设计模式之中的一个。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。
二、UML图
简单工厂主要分为三个角色:工厂(Creator)角色、抽象产品(Product)角色、详细产品(Concrete Product)角色。
工厂角色:该模式核心,它负责创建全部实例的内部逻辑。工厂类能够被外界直接调用。创建所须要的产品。
抽象产品角色:所创建的全部对象的父类,它负责描写叙述全部实例所共同拥有的公共接口。
详细产品:该模式的创建目标,全部创建的对象都是充当这个角色的某个详细类的实例。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ21laTQ5Njg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
三、实例解析
下面是我自己想的一个简单工厂模式场景。假设有不妥的地方还请大家指出。
我做的是一个简易的网吧收费系统。CashFactory充当的是工厂的角色,它会告诉我们怎样创建白天收费方式和晚上收费方式,须要实例化哪些对象,须要什么參数;详细产品 白天、晚上 收费方法。通过override,实现了从基类继承成员的新实现。网吧收费抽象类 为白天和晚上 收费方式的父类,描写叙述了两者的公共接口。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ21laTQ5Njg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
代码例如以下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication2 { public partial class 简易网吧收费系统 : Form { public 简易网吧收费系统() { InitializeComponent(); } //窗口启动的时候载入收费方式,是晚上收费,还是白天收费 private void Form1_Load(object sender, EventArgs e) { cbxTimeType.Items.AddRange(new object[] { "白天", "晚上" });//在时间段的选择框里载入收费选项 白天。晚上 cbxTimeType.SelectedIndex = 0;//索引从0開始,从下往上依次递增 } //单击開始button之后,收费系统開始计时 private void btnOK_Click(object sender, EventArgs e) { lbxList.Items.Add(cbxTimeType .Text ); txtStartTime.Text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");//開始时间文本框获取開始时间 lbxList.Items.Add("開始时间:" + txtStartTime.Text);//同一时候在以下的列表框中载入開始时间信息 } //单击停止button后,收费系统停止计时 private void btnStop_Click(object sender, EventArgs e) { txtEndTime.Text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"); lbxList.Items.Add("结束时间:" + txtEndTime.Text); } //单击结账button,系统開始结账 private void btnCharge_Click(object sender, EventArgs e) { double timeThrough = 0.0d;//定义一个变量timeThrough代表花费的时间(小时) DateTime DateTime1, DateTime2;//定义两个时间变量 DateTime1 = Convert.ToDateTime(txtStartTime.Text);//把文本框中的时间从字符串格式转换成时间格式 DateTime2 = Convert.ToDateTime(txtEndTime.Text); string DateDiff = null;//定义变量时间差(x天x小时x分钟x秒) TimeSpan ts1 = new TimeSpan(DateTime1.Ticks); TimeSpan ts2 = new TimeSpan(DateTime2.Ticks); TimeSpan ts = ts1.Subtract(ts2).Duration(); //计算时间差 DateDiff = ts.Days.ToString() + "天" + ts.Hours.ToString() + "小时" + ts.Minutes.ToString() + "分钟" + ts.Seconds.ToString() + "秒"; timeThrough = Convert.ToDouble (ts.Days.ToString ()) * 24 + Convert.ToDouble (ts.Hours.ToString()) + Convert.ToDouble (ts.Minutes.ToString()) / 60 +Convert.ToDouble ( ts.Seconds.ToString() )/ 3600; lbxList.Items.Add("通过时间:" + DateDiff); //利用简单工厂模式依据下拉选择框,生成对应的对象。 BarCharge barCharge = CashFactory.createCashAccept(cbxTimeType.SelectedItem.ToString()); double money = 0d; money = barCharge.acceptCash(Convert.ToDouble(timeThrough) * 2); lbxList.Items.Add("需要支付上网的费用:" + money +"元");//通过多态,能够得到收取费用的结果 } } //创建一个网吧现金收取的抽象类 abstract class BarCharge { public abstract double acceptCash(double money);//收取现金,參数为原价。返回为当前价 } //网吧的收费机制分为白天和晚上收费两种情况 class Day : BarCharge //白天收费情况 { public override double acceptCash( double money) { return money ;//白天收费,返回钱数 } } class Night : BarCharge //晚上收费情况 { private double moneyRebate = 1d; //晚上收费。初始化必需要输入收费条件,晚上优惠率 public Night(string moneyRebate) { this.moneyRebate = double.Parse(moneyRebate); } //晚上收费=晚上收费*优惠率 public override double acceptCash(double money) { return money * moneyRebate ; } } //现金收费工厂类 class CashFactory { public static BarCharge createCashAccept(string type) { BarCharge bc = null; switch (type)//依据条件返回白天和晚上收费情况 { case "白天": bc = new Day();//实例化对象 break; case "晚上": bc = new Night("0.8");//给出必要參数 break; } return bc; } } }执行结果:
简单工厂攻克了对象的创建问题,免除了直接创建对象的步骤,实现了责任的切割。
可是因为工厂本身包含了全部的收费方式。每次维护或者扩展收费方式都要修改这个工厂,以至于代码须要又一次编译部署。这样违背了开放-封闭原则。
四、感受
走别人的的路,不如自己 to do (不如的意思是更)。
先敲书上的样例,第一遍或许不懂,第二遍就清晰非常多。第三遍就认为自己能写点东西出来。不要总是认为自己看不懂,学不好,仅仅有先学了才干更好。没有之前的8个馒头,就没有第9个馒头的饱(好撑啊~~)。