C# - 设计模式 - 抽象工厂模式


抽象工厂模式

问题场景

有100个方法对Animal类型进行了引用,所以可能需要new100次Animal对象,如果总是使用new创建对象,那么100处都会有对该对象的引用。假如今后Animal被禁止使用,而用另一个具有与Animal类似行为的XAnimal替代Animal,那么你需要在100处使用new创建Animal的地方将代码修改为XAnimal,而假如可以利用抽象将这些引用全部指向一个抽象的实现,比如Animal和XAnimal都从一个Biological的抽象类派生,再用一个专门制造抽象实现的工厂类来返回Biological抽象的实例,再创建一个专门制造XAnimal的工厂类和制造Animal的工厂类,这两个工厂类都从抽象工厂派生,那么今后需求改动时,只需要new一个创建XAnimal的工厂类来创建XAnimal和Animal的共同抽象返回给外部调用即可。

总结模式

工厂模式将所有对具象的引用更改成了对抽象的引用,要使用抽象工厂模式,那么所有的类型都应该从抽象派生,以便彻底解耦对具象类型的依赖。 

示例代码

namespace AppCUI
{
    //动物的抽象
    public abstract class Biological
    {
        public abstract void Say( );
    }

    //动物的具象
    public class Animal : Biological
    {
        public override void Say( )
        {
            Console.WriteLine( "汪汪" );
        }
    }

    //工厂的抽象
    public abstract class Factory
    {
        //创建动物的抽象
        public abstract Biological CreateBiological( );
    }

    //工厂的具象
    public class AnimalFactory : Factory
    {
        //返回一个抽象的实体
        public override Biological CreateBiological( )
        {
            return new Animal( );
        }
    }

    public class Programe
    {
        static void Main( string[] args )
        {
            Factory factory = new AnimalFactory( ); //得到抽象工厂的实现,今后需要XAnimal时,只需要new出一个专门制造XAnimal的工厂类即可
            Biological biological = factory.CreateBiological( ); //得到抽象动物的实现
            biological.Say( );
        }
    }
}

在System.Data.dll中的System.Data.Common.DbProviderFactory抽象工厂就提供了一系列用于创建操作数据库抽象类的抽象方法

public abstract class DbProviderFactory
{
    // 提供了创建具体产品的接口方法
    protected DbProviderFactory( );
    public virtual DbCommand CreateCommand( );
    public virtual DbCommandBuilder CreateCommandBuilder( );
    public virtual DbConnection CreateConnection( );
    public virtual DbConnectionStringBuilder CreateConnectionStringBuilder( );
    public virtual DbDataAdapter CreateDataAdapter( );
    public virtual DbDataSourceEnumerator CreateDataSourceEnumerator( );
    public virtual DbParameter CreateParameter( );
    public virtual CodeAccessPermission CreatePermission( PermissionState state );
}

DbCommand、DbCommandBuilder 、DbConnection 、DbConnectionStringBuilder 、DbDataAdapter 等等都是抽象的类型,DbProviderFactory由SqlClientFactory实现,SqlClientFactory专门创建基于sql的数据库操作类。这样就解耦了对具象的引用,你也可以自定义OracleClientFactory、MySqlClientFactory工厂,实现创建对应的数据库操作类。

public sealed class SqlClientFactory : DbProviderFactory, IServiceProvider
{
    //通过静态的Instance字段获取一个SqlClientFactory实例,确保全局唯一
    public static readonly SqlClientFactory Instance = new SqlClientFactory( );

    // 重写抽象工厂中的方法
    public override DbCommand CreateCommand( )
    {
        // 创建DbCommand的具象
        return new SqlCommand( );
    }

    public override DbCommandBuilder CreateCommandBuilder( )
    {
        return new SqlCommandBuilder( );
    }

    public override DbConnection CreateConnection( )
    {
        return new SqlConnection( );
    }

    public override DbDataAdapter CreateDataAdapter( )
    {
        return new SqlDataAdapter( );
    }

    //……
}

  

C# - 设计模式目录