【大话设计模式】——工厂模式家族

     本博客可能有异常,请结合这篇看:http://www.cnblogs.com/stonehat/archive/2012/04/16/2451891.html

     在工厂模式家族中最出名的是工厂三姐妹,根据抽象的程度不同分为简单工厂工厂模式抽象工厂模式。他们在我们平时的编程中会经常使用。所以我们应该详细地了解一下他们三者之间优缺点。

简单工厂

定义

    简单工厂模式又叫做静态工厂方法(Static FactoryMethod)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

举例说明:  

        25958655_1399530326s3Z6.jpg

代码实现:

 

<span style="font-size:18px;">// 客户端代码
    static void Main(string[] args)
        {
            Operation oper;
            oper = OperationFactory.createOperate("*"); // 父类直接实例化
            oper.NumberA = 1;
            oper.NumberB = 2;
            double result = oper.GetResult();

            
        }
    }

    // Operation运算类
    public 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 OperationMul : 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;
        }
    }

    // 简单运算工厂类
    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 OperationMul();
                    break;
                case "/":
                    oper = new OperationDiv();
                    break;
            }
            return oper;
        }
    }
</span>

 

 

简单工厂的优点:

 

1、工厂类是整个模式的关键.包含了必要的逻辑判断,根据给定的信息,决定究竟应该创建哪个具体类的实例。

2、明确了各自的职责和权利,有利于整个软件体系结构的优化。

简单工厂的缺点:

    1、由于工厂类集中了所有实例的创建逻辑违反了高内聚低耦合原则,将全部创建逻辑集中到了一个工厂类中;

    2、它所能创建的类只能是事先考虑到的,每次扩展都需要更改工厂类,违反了开放封闭原则(即:软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的;适用于抽象编程

 

简单工厂模式的实质由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类的实例

工厂模式

定义:

    用于创建对象的接口让子类决定实例化哪一个类。工厂模式对类的实例化延迟到其子类

    简单来说,工厂模式首先抽象出对对象的共通操作(接口,工厂),之后创建各个具体操作(类,不同工厂),之后创建工厂(类),工厂内部有个方法可以调用具体操作类(实现)。

    这个和简单工厂有区别,简单工厂模式只有一个工厂,工厂方法模式对每一个产品都有相应的工厂

举例说明:数据访问程序       

                25958655_1399530481VM7v.jpg

代码实现:

 

<span style="font-size:18px;">
    static void Main(string[] args)
        {
            // 新用户对象
            User user = new User();
            // 建造工厂,此时没有实例化
            IFactory factory = new SqlServerFactory();
            // 工厂创建用户操作类:工厂内部实现了具体用户操作对象SqlserverUser(基础接口操作IUser实现),实例化
            IUser iu = factory.CreateUser();
            // 用户操作类在表中新增一条用户信息:执行具体用户操作对象SqlserverUser中的操作
            iu.Insert(user);
            // 用户操作类根据ID获得一条用户信息:执行具体用户操作对象SqlserverUser中的操作
            iu.GetUser(1);
            // 下面代码 1:等待键盘输入 2:终止一个程序的执行
            Console.Read();
        }
    }

    // User类
    class User
    {
        private int _id;
        public int ID
        {
            get {return _id;}
            set {_id=value;}
        }
        private string _name;
        public string Name
        {
            get {return _name;}
            set {_name =value ;}
        }
    }

    // IUser接口(用户填入和获取用户对象)
    interface IUser
    {
        void Insert(User user);
        User GetUser(int id);
    }

    // SqlserverUser类
    class SqlserverUser : IUser
    {
        public void Insert(User user)
        {
            Console.WriteLine("在SQL Server 中给User表增加一条记录");
        }
        public User GetUser(int id)
        {
            Console.WriteLine("在SQL Server 中根据ID得到User表一条记录");
            return null;
        }
    }

    // AccessUser类
    class AccessUser : IUser
    {
        public void Insert(User user)
        {
            Console.WriteLine("在Access中给User表增加一条记录");
        }
        public User GetUser(int id)
        {
            Console.WriteLine("在Access中根据ID得到User表一条记录");
            return null;
        }
    }

    // IFactory接口(获取IUser接口,这里是按照抽象工厂的方法写的,实际使用的时候,可直接用下面两个实例化方法)
    interface IFactory
    {
        IUser CreateUser();
    }

    // SqlServerFactory :IFactory
    class SqlServerFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new SqlserverUser();
        }
    }

    // AccessFactory类
    class AccessFactory:IFactory 
    {
        public IUser CreateUser()
        {
            return new AccessUser();
        }
    }
</span>

 

 

工厂模式的优点:

        1、克服了简单工厂违背开放封闭原则的缺点,保持了封装的优点。工厂模式集中封装了对象的创建,更换对象时更加容易。
        2、使用了多态性,保持了简单工厂的优点。
        3、降低耦合度。降低了客户程序与产品对象的耦合。

        4、增加一个运算类(例如N次方类),只需要增加运算类相对应的工厂,两个类,不需要修改工厂类(右图)。

     缺点:

        1、增加运算类,会修改客户端代码,工厂方法只是把简单工厂的内部逻辑判断移到了客户端进行(右图)。 

 

抽象工厂

定义:

    创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类

举例说明:数据访问程序

 

             25958655_1399530523DmFr.jpg

代码实现:

 

<span style="font-size:18px;"> 
    static void Main(string[] args)
        {
            // 新用户对象
            User user=new User ();
            // 部门,专业
            Department dept = new Department();
            //IFactory factory = new SqlServerFactory();
            // access工厂
            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();
            
        }
    }

    // 用户类
    class User   
    {
        private int _id;
        public int ID
        {
            get {return _id;}
            set {_id =value;}
        }
        private string _name;
        public string Name
        {
            get {return _name ;}
            set {_name =value ;}
        }
    }

    // IUser接口
    interface IUser 
    {
        void Insert(User user);
        User GetUser(int id);
    }

    // IUser接口的子SqlserverUser类,用于访问SQL Server的User
    class SqlserverUser :IUser 
    {
        public void Insert(User user)
        {
            Console.WriteLine("在SQL Server中给User表增加一条记录");
        }
        public User GetUser(int id)
        {
            Console.WriteLine ("在SQL Server中根据ID得到User表一条记录");
            return null;
        }
    }

    // IUser接口的子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;
        }
    }

    // 增加一个Department表
    class Department
    {
        private int _id;
        public int ID
        {
            get { return _id; }
            set { ID = value; }
        }
        private string _deptName;
        public string DeptName
        {
            get { return _deptName; }
            set { DeptName = value; }
        }
    }

    // IDpartment接口
    interface IDepartment
    {
        void Insert(Department department);

        Department GetDepartment(int id);
    }

    // sqlserverDepartment类
    class SqlserverDepartment : IDepartment
    {
            public void Insert(Department department)
            {
                Console.WriteLine("在SQL Server中给Department表增加一条记录");
            }
            public Department GetDepartment(int id)
            {
                Console.WriteLine("在SQL Server中根据ID得到Department表一条记录");
                return null;
            }
    }

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

    // 抽象工厂的接口
    interface IFactory
    {
        IUser CreateUser();
        IDepartment CreateDepartment(); //增加的接口方法
    }

    class SqlServerFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new SqlserverUser();
        }
        public IDepartment CreateDepartment()
        {
            return new AccessDepartment();
        }
    }

    class AccessFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new AccessUser();
        }
        public IDepartment CreateDepartment()
        {
            return new AccessDepartment();
        }
    }
</span>

 

抽象工厂的优点:

 

    抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部创建不同的产品对象

抽象工厂的缺点:

    对于增加需求,扩展程序时,需要增加许多子类,使得程序变得臃肿,麻烦。(此时可以利用反射+抽象工厂的方法避免)。

 

总结:

 

        无论是简单工厂模式,工厂模式,还是抽象工厂模式,他们都属于工厂模式,并且是创建型模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦

转载于:https://my.oschina.net/zhumenzhongren/blog/672767

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值