//抽象工厂接口 public interface ICreator { ProductA factoryA();//创建A族产品 ProductB factoryB();//创建B族产品 }
//具体工厂类1 public class ConcreteCreator1 implements ICreator { @Override public ProductA factoryA() { return new ConcreteProductA1(); } @Override public ProductB factoryB() { return new ConcreteProductB1(); } } //具体工厂类2 public class ConcreteCreator2 implements ICreator { @Override public ProductA factoryA() { return new ConcreteProductA2(); } @Override public ProductB factoryB() { return new ConcreteProductB2(); } }
//调用类 public class Client { public static void main(String[] args) { ICreator creator1=new ConcreteCreator1(); ICreator creator2=new ConcreteCreator2(); ProductA proa1=creator1.factoryA(); ProductB prob1=creator1.factoryB(); ProductA proa2=creator2.factoryA(); ProductB prob2=creator2.factoryB(); //.... } }
这里我要提出的问题是具体工厂类的实现中,每个工厂方法返回类型都是抽象类,而具体要返回哪个实现类并未规定,可以返回任何子类。 这里返回的实际子类对调用者是透明的。如ConcreteCreator1的factoryA方法可以返回ConcretProductA2,客户端本来想要调用ConcreteCreator1得到ConcretProductA1,结果可能是ConcretProductA2。
问题出现的原因是一个具体工厂类中所生产的不同类型的产品之间没有关联,以至程序员们可以随意搭配,这样抽象工厂已经毫无意义了。而抽象工厂的意义正是在于它要生产的是一组有关联的产品族,从代码的角度来说工厂实现类各工厂方法所生产的实际产品必须是有关联的。下面我们以C#的ado.net抽象工厂DbProviderFactory为例说明,先看一段普通的数据库查询代码:
string connStr = "Persist Security Info=False;Initial Catalog=mydb;server=(local);User ID=sa;Pwd=xxx"; string sql = "select * from userinfo where id=@id"; using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); SqlCommand cmd = new SqlCommand(sql,conn); SqlParameter param = new SqlParameter(); param.ParameterName = "id"; param.DbType = DbType.Int32; param.Value = 4; cmd.Parameters.Add(param); SqlDataReader dataReader = cmd.ExecuteReader(); if (dataReader.Read()) { Console.WriteLine(dataReader.GetString(0)); } }这段使用System.Data.SqlClient查询数据的代码很常见,但按依赖倒转原则来说它与System.Data.SqlClient耦合太深了。.net中数据提供程序还有System.Data.Odbc、System.Data.OleDb、 System.Data.OracleClient等,如果换了其他数据提供程序那我们整个代码都得被翻新一遍了。
DbProviderFactory DbProvider = SqlClientFactory.Instance; using (DbConnection conn = DbProvider.CreateConnection()) { conn.Open(); DbCommand cmd = DbProvider.CreateCommand(); cmd.Connection = conn; cmd.CommandText = sql; DbParameter param = DbProvider.CreateParameter(); param.ParameterName = "id"; param.DbType = DbType.Int32; param.Value = 4; cmd.Parameters.Add(param); DbDataReader dataReader = cmd.ExecuteReader(); if (dataReader.Read()) { Console.WriteLine(dataReader.GetString(0)); } }现在只需修改具体工厂即可实现数据提供程序的转换,程序与数据提供器的解耦正是通过抽象工厂模式完美实现。
抽象工厂模式的解读与使用注意点,布布扣,bubuko.com
原文:http://blog.csdn.net/jqncc/article/details/20698159