简单工厂模式、工厂方法模式、反射工厂模式、抽象工厂模式

        工厂模式在当初学习.net时就听说过,记得当初实习的简历上写着熟悉三层架构和工厂模式,其实当初并不会,只是听说过。直到前些时候才去了解工厂模式,其实工厂模式还是很常用的,参考大话设计模式和网上的若干博客,初步整理出四种版本的,简单工厂模式、工厂模式、改进的反射工厂模式、抽象工厂模式。
        首先先大概了解下实际运用背景,比如要设计一个集成平台将停车场集成进来,而停车场有多个品牌供用户选择,这种情况就需要运用工厂模式。将停车场的特征方法提取出来,每新加一种停车场时实现该方法即可,客户端只需少许更改即可实现动态选择产品。
        首先不使用工厂模式实现:

public class ParkA 
{
    public void GetParkInfo()
    {
        Console.WriteLine("ParkA");
    }
}
public class ParkB
{
    public void GetParkInfo()
    {
        Console.WriteLine("ParkB");
    }
}

        客户端:

class Program
{
    static void Main(string[] args)
    {
        ParkA park = new ParkA();
        park.GetParkInfo();
        Console.ReadLine();
    }
}

        这客户端是用ParkA,又一客户用ParkB,把这段代码去掉换成ParkB交给客户,第三个客户用ParkA,只能再改回ParkA,第一个客户和第三个客户明明一样,但也没法直接用(因为第二个客户时已经改成ParkB了),如此很多时侯就是在做重复劳动,而且每卖一个都要开发人员根据其品牌修改一番。
1.简单工厂
        简单工厂上场,面向接口编程,将选择品牌的过程交给客户,将停车场提取出接口,每个品牌都实现这个接口,然后提供一个工厂,用户只要选择自己的品牌即可。

public interface IPark
{
    void GetParkInfo();
}
public class ParkA : IPark
{
    public void GetParkInfo()
    {
        Console.WriteLine("ParkA");
    }
}
public class ParkB : IPark
{
    public void GetParkInfo()
    {
        Console.WriteLine("ParkB");
    }
}
public enum ParkTypeEnum
{
    ParkA,
    ParkB
}
public class ParkFactory
{
    public static IPark CreatePark(ParkTypeEnum parkType)
    {
        switch (parkType)
        {
            case ParkTypeEnum.ParkA:
                return new ParkA();
            case ParkTypeEnum.ParkB:
                return new ParkB();
            default:
                return null;
        }
    }
}

        客户端:

class Program
{
    static void Main(string[] args)
    {
        IPark park = ParkFactorys.ParkFactory.CreatePark(ParkTypeEnum.ParkA);
        park.GetParkInfo();
        Console.ReadLine();
    }
}

        当有新品牌时只需实现接口,修改工厂即可。而对于已有的品牌则无需修改。
        这里有个理论依据,里氏替换法则:任何接收父类型的地方,都应当能够接收子类型,换句话说如果使用的是一个基类的话,那么一定适用于其子类,而且程序察觉不出基类对象和子类对象的区别。
        开放封闭原则:对扩展是开放的,而对修改是封闭的。
        缺点:违反了开放封闭原则,对修改开放了,在增加一个新的品牌时必须相应增加工厂的switch分支。
2.工厂模式
        相对简单工厂变化之处,就是工厂发生了变化,将工厂也抽象出来一个工厂接口,里面只有一个方法,用来创建实例。每个品牌都有自己的工厂,各自实现工厂接口即可。

public interface IPark
{
    void GetParkInfo();
}
public class ParkA : IPark
{
    public void GetParkInfo()
    {
        Console.WriteLine("ParkA");
    }
}
public class ParkB : IPark
{
    public void GetParkInfo()
    {
        Console.WriteLine("ParkB");
    }
}
public interface IFactoryPark
{
    IPark CreatePark();
}
public class ParkFactoryA : IFactoryPark
{
    public IPark CreatePark()
    {
        return new ParkA();
    }
}
public class ParkFactoryB : IFactoryPark
{
    public IPark CreatePark()
    {
        return new ParkB();
    }
}

        客户端:

class Program
{
    static void Main(string[] args)
    {
        IFactoryPark factory = new ParkFactoryA();
        IPark park=factory.CreatePark();
        park.GetParkInfo();
        Console.ReadLine();
    }
}

        这样就符合了开放封闭原则,新加品牌同时新加相应的工厂,而无需修改原有的工厂。
        缺点:品牌多了之后工厂也会随之变得很多。
3.反射工厂模式
        针对简单工厂模式,还有一种改进,利用反射来封闭修改。修改工厂类,如下:

public class ParkFactory
{
    public static IPark CreatePark(string typeName)
    {
        #region 方法一
        //load中是程序集的名称,也就是生成的DLL的名称
        //CreateInstance后面的是类的完整名称,带命名空间
        //IPark park = Assembly.Load("ParkFactorys").CreateInstance(typeName) as IPark;
        #endregion
        #region 方法二
        //GetType的参数需是类的完整名称,带命名空间
        Type type = Type.GetType(typeName, true);
        IPark park = Activator.CreateInstance(type) as IPark;
        #endregion
        return park;
    }
}

        客户端:

class Program
{
    static void Main(string[] args)
    {
        IPark park = ParkFactory.CreatePark("ParkFactorys.ParkA");
        park.GetParkInfo();
        Console.ReadLine();
    }
}

4.抽象工厂模式

        以上的三种的产品扩展都是针对同一个系列,当有多个时需要工厂里将每个系列一个个的抽象,这时就要抽象工厂模式。
        比如如下例子,除了集成停车场,现在也要集成汽车,这时就需要在工厂接口里增加创建汽车接口的方法,抽象工厂是对工厂模式的继续扩充。

public interface IPark
{
    void GetParkInfo();
}
public class ParkA : IPark
{
    public void GetParkInfo()
    {
        Console.WriteLine("ParkA");
    }
}
public class ParkB : IPark
{
    public void GetParkInfo()
    {
        Console.WriteLine("ParkB");
    }
}
public interface ICar
{
    void Run();
}
public class CarA : ICar
{
    public void Run()
    {
        Console.WriteLine("CarA Run");
    }
}
public class CarB : ICar
{
    public void Run()
    {
        Console.WriteLine("CarB Run");
    }
}
public interface IFactory
{
    IPark CreatePark();
    ICar CreateCar();
}
public class ParkFactoryA : IFactory
{
    public IPark CreatePark()
    {
        return new ParkA();
    }

    public ICar CreateCar()
    {
        return new CarA();
    }
}
public class ParkFactoryB : IFactory
{
    public IPark CreatePark()
    {
        return new ParkB();
    }

    public ICar CreateCar()
    {
        return new CarB();
    }
}

        客户端:

class Program
{
    static void Main(string[] args)
    {
        IFactory factory = new ParkFactoryA();
        IPark park=factory.CreatePark();
        park.GetParkInfo();
        ICar car = factory.CreateCar();
        car.Run();
        Console.ReadLine();
    }
}

        最后简单的总结:
        简单工厂:简单实用,但违反开放封闭;
        工厂方法:开放封闭,单一产品;
        抽象工厂:开放封闭,多个产品;
        反射工厂:可以最大限度的解耦。 

        源码下载

你可能感兴趣的:(设计模式)