hhh2016

一、简单工厂模式

简单工厂模式,提供了一种创建对象的便捷方法。创建者通过不同的类型参数,创建相对应的对象。

实现代码如下:

 public class Product
    {
        public virtual void Funtion()
        {}
    }

    public class ProductA : Product
    {
        public override void Funtion()
        {
            base.Funtion();
        }
    }

    public class ProductB : Product
    {
        public override void Funtion()
        {
            base.Funtion();
        }
    }

    public class Creator
    {
        public static Product Create(string type)
        {
            switch (type)
            { 
                case "A":
                    return new ProductA();
                case "B":
                    return new ProductB();
                default:
                    return null;           
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Product pa = Creator.Create("A");
        }
    }

优点:

在创建固定类型的对象时,比较简单好用。

缺点:

1. 在添加对象类型时,需要更改Creator类里面的函数,违反了软件设计中的开闭原则。

2. Creator类依赖于具体类ProductA,和ProductB,在具体类变化时直接影响Creator类,耦合性过强。

工厂模式

         工厂模式将对象的创建延迟到了具体的子类里面实现。这样,我们创建子类对象时,不需要知道具体的子类,只需获取到相应的类型的工厂即可。同时,工厂模式消除了简单工厂方法所具有高耦合性,且满足软件的设计原则。

         工厂模式,解决了创建多个、同类对象的复杂问题。比如我们需要创建100个ProductA种类的对象,如果不使用工厂模式,我们需要new出100个ProductA对象来;通过工厂模式,只需要调用FactoryA多次就能够完成对象的创建。

1. 实现方法

1)工厂模式最常用的结构类图:

实现代码(C#)如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Factory
{
    public class Product
    {
        public virtual void Funtion()
        { }
    }

    public class ProductA : Product
    {
        public override void Funtion()
        {
            base.Funtion();
        }
    }

    public class ProductB : Product
    {
        public override void Funtion()
        {
            base.Funtion();
        }
    }

    public class Factory
    {
        virtual public Product Create()
        {
            return null;
        }
    }

    public class FacotryA : Factory
    {
        public override Product Create()
        {
            return new ProductA();
        }
    }

    public class FactoryB : Factory
    {
        public override Product Create()
        {
            return new ProductB();
        }
    }

    class FactoryMode
    {
        static void Main(string[] args)
        {
            FacotryA fa = new FacotryA();
            FactoryB fb = new FactoryB();

            Product pa = fa.Create();
            Product pb = fb.Create();
        }
    }
}

工厂模式的问题在于,每添加一种新的Product必须添加与之相对应的Factory类。比如,现在需要增加一种对象ProductC,同时需要添加FactoryC类来创建ProductC的对象。这样的话,如果需要添加N多种对象,同时就必须添加与之对应的N种工厂类,增加了编码量和繁琐程度,如下图。

2)使用类模板 

         在需要添加多种对象时,采用模版的方式,可以避免创建过多的工厂子类。

此处,只需要定义一个类模板template<class TheProduct> ConcreteFactoy,只要是从Product基类派生的对象类型,都可以通过这个类模板实现。

以下是实现代码(C++).

 

#include "stdafx.h"
#include <iostream>

using namespace std;

class Product
{
public:
    virtual void Function() = 0;
};

class ProductA : public Product
{
public:
    void Function();
};

void ProductA::Function()
{
    cout << "Create ProductA..." << endl;
}

class Factory
{
public:
    virtual Product* Create() = 0;
};

template<class TheProduct>
class ConcreteFactroy : public Factory
{
public:
    virtual Product* Create();
};

template<class TheProduct> 
Product* ConcreteFactroy<TheProduct>::Create()
{
    return new TheProduct;
}


int _tmain(int argc, _TCHAR* argv[])
{
    ConcreteFactroy<ProductA> MyFactory; 
    Product* pa = MyFactory.Create();
    pa->Function();

    return 0;
}

 

3. 抽象工厂

         抽象工厂模式,用于创建一组相关或独立的对象。通过此模式,用户不需要知道具体的对象类型,只需找到创建的工厂类即可。抽象工厂与工厂方法的区别主要如下:

         工厂方法中的工厂类只能创建一种对象,如FactoryA -> ProductA。

         抽象工厂中的工厂类可以创建多种类型的对象, Factory1 -> {product1, product2, …,productN}

抽象工厂的问题在于,当我们需要添加新的对象AbstractProductC时,需要同时修改AbstractFactory, ConcreteFactory1和ConcreteFactory2三个类。从这个角度来看,添加新类型的对象时,与简单工厂模式类似。这里,我们不妨就先把抽象工厂更改为简单工厂模式,然后再通过反射机制进行改进。通过反射,用户只需要传递product子类型的名字给Factory类。Factory类根据传入的类名字,生成类对象。无论后期添加多少种对象,都不用再添加对应的工厂类。

以下描述了,抽象工厂模式访问数据库,然后更改为简单工厂模式,再使用反射机制的整个过程(摘自《大话设计模式》)。(其实,三种工厂模式都可以使用反射机制来简化对象生成的过程。)

使用抽象工厂访问数据库的类图:

 

我们将抽象工厂更改为简单工厂模式,如下:

使用反射实现(C#),如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Reflection;


namespace AbstractFactory
{
    public interface IUser
    {
        void InsertUser(IUser user);

        IUser GetUser(string user);
    }


   public class SQLUser : IUser
   {
       public void InsertUser(IUser user)
       {
           Console.WriteLine("Access user");
       }

       public IUser GetUser(string user)
       {
           return null;
       }
   }

   public class AccessUser : IUser
   {
       public void InsertUser(IUser user)
       {
           Console.WriteLine("Access user");
       }

       public IUser GetUser(string user)
       {
           return null;
       }
   }

   public class DataAccess
   {
       private readonly string dbType = "SQL";
       public IUser CreateUser()
       {
           IUser result = null;
           switch (dbType)
           {
               case "SQL":
                   result = new SQLUser();
                   break;
               case "Access":
                   result = new AccessUser();
                   break;
               default:
                   break;
           }
           return result;
       }

       public string ReflectType { get; set; }

       public IUser CreateUserByReflection()
       {
           //(IUser)Assembly.Load(当前程序集的名称 "Factory").CreateInstance("命名空间.类名");
           return (IUser)Assembly.Load("Factory").CreateInstance(ReflectType);         
       }
   }

    class AbstractFactory_Reflect
    {
        static void Main(string[] args)
        {
            DataAccess da = new DataAccess();
            da.ReflectType = "AbstractFactory.SQLUser";

            IUser user = null;
            user = da.CreateUserByReflection();

            SQLUser sqlUser = user as SQLUser;
            if (sqlUser == null)
            {
                Console.WriteLine("NULL...");
            }
        }
    }
}

 

分类:

技术点:

相关文章:

  • 2021-07-10
  • 2022-12-23
  • 2021-12-14
  • 2021-11-28
  • 2022-12-23
  • 2021-09-24
  • 2021-05-29
  • 2022-01-31
猜你喜欢
  • 2022-12-23
  • 2022-03-09
  • 2021-04-06
  • 2021-06-02
  • 2022-03-10
  • 2021-09-21
相关资源
相似解决方案