zoukankan      html  css  js  c++  java
  • 【大话设计模式】——简单工厂模式

    一、概念

      简单工厂模式(Simple Factory Pattern)属于创建型模式,又叫做静态工厂方法模式(Static FactoryMethod Pattern),可是不属于23GOF设计模式之中的一个。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。


    二、UML图

      简单工厂主要分为三个角色:工厂(Creator)角色、抽象产品(Product)角色、详细产品(Concrete Product)角色。

      工厂角色:该模式核心,它负责创建全部实例的内部逻辑。工厂类能够被外界直接调用。创建所须要的产品。

      抽象产品角色:所创建的全部对象的父类,它负责描写叙述全部实例所共同拥有的公共接口。

           详细产品:该模式的创建目标,全部创建的对象都是充当这个角色的某个详细类的实例。


    三、实例解析

      下面是我自己想的一个简单工厂模式场景。假设有不妥的地方还请大家指出。

      我做的是一个简易的网吧收费系统。CashFactory充当的是工厂的角色,它会告诉我们怎样创建白天收费方式和晚上收费方式,须要实例化哪些对象,须要什么參数;详细产品 白天、晚上 收费方法。通过override,实现了从基类继承成员的新实现。网吧收费抽象类 为白天和晚上 收费方式的父类,描写叙述了两者的公共接口。




    代码例如以下:

    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个馒头的饱(好撑啊~~)。

  • 相关阅读:
    缓存雪崩与缓存穿透
    读取表中最大值
    使用vscode在谷歌上运行代码
    elment 中tree组件展开所有和收缩所有节点
    深度系统商店提示无法安装软件依赖错误
    诗词,理解,品论
    《45个十分钟读懂资本论》原文、适合朗读版和个人见解
    《论持久战》全文
    OSError: [WinError 126] 找不到指定的模块。
    C++ 获取序列最大(或最小)的 N 个元素
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7241623.html
Copyright © 2011-2022 走看看