设计模式---创建型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Yue510/article/details/84074446

创建型设计模式:
创建型模式(Creational Pattern)对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。

  • 简单工厂模式(Simple Factory)
  • 工厂方法模式(Factory Method)定义一个用于创建对象的接口,让子类决定实例化哪个类。Factory Method使一个类的实例化延迟到其子类。
  • 抽象工厂模式(Abstract Factory)提供一个创建一系列或互相依赖对象的接口,而无需指定它们具体的类。
  • 建造者模式(Builder)将一个复杂对象的构建与它的表示分离,使同样的构建过程可以创建不同的表示。
  • 原型模式(Prototype)用原型实例指定创建对象的种类,并且通过复制这些原创创建新的对象。
  • 单例模式(Singleton)保证一个类仅有一个实例,并提供一个全局访问点。

简单工厂模式
功能:主要用于创建对象。新添加类时,不会影响以前的系统代码。核心思想是用一个工厂来根据输入的条件产生不同的类,然后根据不同类的virtual函数得到不同的结果。
优点: 适用于不同情况创建不同的类时
缺点: 客户端必须要知道基类和工厂类,耦合性差
模式结构:
Factory:工厂角色负责实现创建所有实例的内部逻辑
Product:抽象产品角色是所创建的所有对象的父类,负责描述所有实例所共有的公共接口
ConcreteProduct:具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。

简单工厂模式实现程序

//运算类
    class OPeration
    {
        private double _numberA = 0;
        private double _numberB = 0;

        public double NumberA
        {
            get { return _numberA; }
            set { _numberA = value; }
        }
        public double NumberB
        {
            get { return _numberB; }
            set { _numberB = value; }
        }
        public virtual double GetResult()
        {
            double result = 0;
            return result;
        }
    }
    //加减乘除类
    class OperationAdd : Operation   //加法类
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA + NumberB;
            return result;
        }
    }

    
    class OperationSub : Operation  //减法类    
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA - NumberB;
            return result;
        }
    }


    class OpertionMul : Operation   //乘法类
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA * NumberB;
            return result;
        }
    }


    class OperationDiv : Operation  //除法类
    {
        public override double GetResult()
        {
            double result = 0;
            if (NumberB==0)
            {
                throw new Exception("除数不能为0");
            }
            result = NumberA / NumberB;
            return result;
        }
    }
//简单运算工厂类
    public class OperationFactory
    {
        public static Operation createOperate(string operate)
        {
            Operation oper = null;
            switch (operate)
            {
                case "+":
                    oper = new OperationAdd();
                    break;
                case "-":
                    oper = new OperationSub();
                    break;
                case "*":
                    oper = new OpertionMul();
                    break;
                case "/":
                    oper = new OperationDiv();
                    break;
            }
            return oper;
        }
    }
//客户端代码
    class Program
    {
        public static void Main(string[] args)
        {
            Operation oper;
            oper = OperationFactory.createOperate("-");
            oper.NumberA = 1;
            oper.NumberB = 2;
            double result = oper.GetResult();
            Console.WriteLine(result);
            
            Console.ReadLine();
        }
    }

工厂方法模式(多态工厂模式)
功能:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
优点:
向客户隐藏了哪种具体产品将被实例化的细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,无须知道具体产品类的类名。
基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
系统中加新产品时,无须修改抽象工厂和抽象产品的接口,(但要修改客户端,以选择不同的具体工厂!),无须修改其他的具体工厂和产品,而只要添加一个具体工厂和具体产品即可。符合“开闭原则”。
缺点:
在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,一定程度上增加了系统复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

工厂方法模式实现程序

 //雷锋类
    class LeiFeng
    {
        public void Sweep()
        {
            Console.WriteLine("扫地");
        }

        public void Wash()
        {
            Console.WriteLine("洗衣");
        }

        public void BuyRice()
        {
            Console.WriteLine("买米");
        }
    }
    //学雷锋的大学生类
    class Undergraduate : LeiFeng
    {

    }
    //社区志愿者
    class Volunteer : LeiFeng
    {

    }
    //雷锋工厂
    interface IFactory
    {
        LeiFeng CreateLeiFeng();
    }
    //学雷锋的大学生工厂
    class UndergraduateFactory : IFactory
    {
        public LeiFeng CreateLeiFeng()
        {
            return new Undergraduate();
        }
    }
    //社区志愿者工厂
    class VolunteerFactory : IFactory
    {
        public LeiFeng CreateLeiFeng()
        {
            return new Volunteer();
        }
    }
    //客户端
    class Program
    {
        static void Main(string[] args)
        {
            //工厂方法模式
            IFactory factory = new UndergraduateFactory();
            LeiFeng student = factory.CreateLeiFeng();

            student.BuyRice();
            student.Sweep();
            student.Wash();

            Console.Read();
        }
    }

在这里插入图片描述

抽象工厂模式(Kit模式)
功能:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
优点:
抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,此模式可以实现高内聚低耦合的设计目的。
当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,很实用。
增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
缺点:
在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。
开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)。

抽象工厂模式实现程序

 //用户表
    class User
    {
        private int _id;
        private int ID
        {
            get { return _id; }
            set { _id = value;}
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    }
    //SqlserverUser类 用于访问SQLServer的User
    class SqlserverUser : IUser
    {
        public void Insert(User user)
        {
            Console.WriteLine("在SQLServer中根据ID得到User表一条记录");            
        }

        public User GetUser(int id)
        {
            Console.WriteLine("在SQLServer中根据id得到User表一条记录");
            return null;
        }
    }
    //IUser接口 用于客户端的访问,解除与具体数据库访问的耦合
    interface IUser
    {
        void Insert(User user);
        User GetUser(int id);
    }
    //AccessUser类 用于访问Access的User
    class AccessUser : IUser
    {
        public void Insert(User user)
        {
            Console.WriteLine("在Access中给User表增加一条记录");
        }

        public User GetUser(int id)
        {
            Console.WriteLine("在Access中根据ID得到User表一条记录");
            return null;
        }
    }
    //抽象工厂接口 定义一个创建访问User表对象的抽象工厂接口+Department
    interface IFactory
    {
        IUser CreateUser();

        IDepartment CreateDepartment();
    }
    //SqlServerFactory类 实现IFactory接口,实例化SqlserverUser和SqlserverDepartment
    class SqlServerFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new AccessUser();
        }

        public IDepartment CreateDepartment()
        {
            return new SqlserverDepartment();
        }
    }
    //AccessFactory类 实现IFactory接口,实例化AccessUser和AccessDepartment
    class AccessFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new AccessUser();
        }

        public IDepartment CreateDepartment()
        {
            return new AccessDepartment();
        }
    }
    //部门表
    class Department
    {
        private int _id;
        private int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        private string _deptName;
        public string DeptName
        {
            get { return _deptName; }
            set { _deptName = value; }
        }

    }
    //IDepartment接口 用于客户端访问,解除与具体数据库访问的耦合
    interface IDepartment
    {
        void Insert(Department department);

        Department GetDepartment(int id);
    }
    //SqlserverDepartment类 用于访问SQLServer的Department
    class SqlserverDepartment : IDepartment
    {
        public void Insert(Department department)
        {
            Console.WriteLine("在SQLServer中给Department表增加一条记录");
        }

        public Department GetDepartment(int id)
        {
            Console.WriteLine("在SQLServer中根据ID得到Department表一条记录");
            return null;
        }
    }
    //AccessDepartment类 用于访问Access的Department
    class AccessDepartment : IDepartment
    {
        public void Insert(Department department)
        {
            Console.WriteLine("在Access中给Department表增加一条记录");
        }

        public Department GetDepartment(int id)
        {
            Console.WriteLine("在Access中根据ID得到Department表一条记录");
            return null;
        }
    }
    //抽象工厂接口 定义一个创建访问User表对象的抽象工厂接口+Department
    interface IFactory
    {
        IUser CreateUser();

        IDepartment CreateDepartment();
    }
    //SqlServerFactory类 实现IFactory接口,实例化SqlserverUser和SqlserverDepartment
    class SqlServerFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new AccessUser();
        }

        public IDepartment CreateDepartment()
        {
            return new SqlserverDepartment();
        }
    }
    //AccessFactory类 实现IFactory接口,实例化AccessUser和AccessDepartment
    class AccessFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new AccessUser();
        }

        public IDepartment CreateDepartment()
        {
            return new AccessDepartment();
        }
    }
    //客户端
    class Program
    {
        static void Main(string[] args)
        {
            User user = new User();
            Department dept = new Department();

            //IFactory factory = new SqlServerFactory();

            IFactory factory = new AccessFactory();

            IUser iu = factory.CreateUser();

            iu.Insert(user);
            iu.GetUser(1);

            IDepartment id = factory.CreateDepartment();
            id.Insert(dept);
            id.GetDepartment(1);

            Console.Read();
        }
    }

在这里插入图片描述

建造者模式(生成器模式)
功能:
将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
优点:
客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
每一个具体建造者都独立,因此可以方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象 。
可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭”。
缺点:
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,若产品之间的差异性很大,则不适合使用该模式,因此其使用范围受到一定限制。
若产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。

建造者模式实现程序

 //建造人的类
    abstract class PersonBuilder
    {
        protected Graphics g;
        protected Pen p;

        public PersonBuilder(Graphics g, Pen p)
        {
            this.g = g;
            this.p = p;
        }

        public abstract void BuildHead();
        public abstract void BuildBody();
        public abstract void BuildArmLeft();
        public abstract void BuildArmRight();
        public abstract void BuildLegLeft();
        public abstract void BuildLegRight();
    }
    //瘦子类
    class PersonThinBuilder : PersonBuilder
    {
        public PersonThinBuilder(Graphics g, Pen p) : base(g, p)
        { }

        public override void BuildHead()
        {
            g.DrawEllipse(p, 50, 20, 30, 30);
        }

        public override void BuildBody()
        {
            g.DrawRectangle(p, 60, 50, 10, 50);    
        }

        public override void BuildArmLeft()
        {
            g.DrawLine(p, 60, 50, 40, 100);
        }

        public override void BuildArmRight()
        {
            g.DrawLine(p, 70, 50, 90, 100);
        }

        public override void BuildLegLeft()
        {
            g.DrawLine(p, 60, 100, 45, 150);
        }

        public override void BuildLegRight()
        {
            g.DrawLine(p, 70, 100, 85, 150);
        }
    }
    //指挥者类
    class PersonDirector
    {
        private PersonBuilder pb;
        public PersonDirector(PersonBuilder pb)
        {
            this.pb = pb;
        }

        public void CreatePerson()
        {
            pb.BuildHead();
            pb.BuildBody();
            pb.BuildArmLeft();
            pb.BuildArmRight();
            pb.BuildLegLeft();
            pb.BuildLegRight();
        }
    }
        //图片框的单击事件
        private void pictureBox1_Click(object sender, EventArgs e)
        {
            Pen p = new Pen(Color.Red);
            PersonThinBuilder pfb = new PersonThinBuilder(pictureBox1.CreateGraphics(), p);
            PersonDirector pdThin = new PersonDirector(pfb);
            pdThin.CreatePerson();

            Console.Read();
        }

在这里插入图片描述

单例模式
功能:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
优点:
提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。
由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。
允许可变数目的实例。我们可以基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例。
缺点:
由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。
滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;现在很多面向对象语言(如Java、C#)的运行环境都提供了自动垃圾回收的技术,因此,如果实例化的对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致对象状态的丢失。

单例模式实现程序

 //Form1窗体
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private FormToolbox ftb;
        private void toolStripMenuItemToolboxToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormToolbox.GetInstance().Show();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            FormToolbox.GetInstance().Show();
        }


        private void Form1_Load(object sender, EventArgs e)
        {
            this.IsMdiContainer = true;
        }
    }
    //FormToolbox窗体
    public partial class FormToolbox : Form
    {
        private static FormToolbox ftb = null;
        private FormToolbox()
        {
            InitializeComponent();
        }

        public static FormToolbox GetInstance()
        {
            if (ftb == null || ftb.IsDisposed)
            {
                ftb = new FormToolbox();
                ftb.MdiParent = Form1.ActiveForm;
            }
            return ftb;
        }
        private void FormToolbox_Load(object sender, EventArgs e)
        {

        }
    }

在这里插入图片描述

原型模式
功能:
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。原型模式其实就是从一个对象创建另外一个可定制的对象,而且不需知道任何创建的细节。
优点:   
一般在初始化的信息不发生变化的情况下,克隆是最好的办法,既隐藏了对象创建细节,又提高性能。其等于是不用重新初始化对象,而是动态地获得对象运行时的状态。

原型模式实现程序

//工作经历类
    class WorkExperience : ICloneable
    {
        private string workDate;
        public string WorkDate
        {
            get { return workDate; }
            set { workDate = value; }
        }

        private string company;
        public string Company
        {
            get { return company; }
            set { company = value; }
        }

        public Object Clone()
        {
            return (object)this.MemberwiseClone();
        }
    }
   //简历类
    class Resume : ICloneable
    {
        private string name;
        private string sex;
        private string age;
        private WorkExperience work;

        public Resume(string name)
        {
            this.name = name;
            work = new WorkExperience();
        }

        private Resume(WorkExperience work)
        {
            this.work = (WorkExperience)work.Clone();
        }

        //设置个人信息
        public void SetPersonalInfo(string sex, string age)
        {
            this.sex = sex;
            this.age = age;
        }

        //设置工作经历

        public void SetWorkExperience(string workDate, string company)
        {
            work.WorkDate = workDate;
            work.Company = company;
        }

        //显示
        public void Display()
        {
            Console.WriteLine(" {0} {1} {2}", name, sex, age);
            Console.WriteLine("工作经历: {0} {1}", work.WorkDate, work.Company);
        }

        public Object Clone()
        {
            Resume obj = new Resume(this.work);
            obj.name = this.name;
            obj.sex = this.sex;
            obj.age = this.age;
            return obj;
        }
    }
   //客户端代码
    class Program
    {
        static void Main(string[] args)
        {
            Resume a = new Resume("大鸟");
            a.SetPersonalInfo("男", "29");
            a.SetWorkExperience("1998-2000", "xx公司");

            Resume b = (Resume)a.Clone();
            b.SetWorkExperience("2000-2009", "yy公司");

            Resume c = (Resume)a.Clone();             
            c.SetWorkExperience("2009-2018", "zz企业");

            a.Display();
            b.Display();
            c.Display();

            Console.Read();
        }
    }

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Yue510/article/details/84074446