我读设计模式之简单工厂模式

     书上说简单工厂模式不是23种经典设计模式中得一种。但不管怎么样,作为一种编程的思想,还是很有必要学习一下。


     简单工厂模式的核心是通过建立工厂类,此工厂类根据传递的参数不同,实例化不同的具体类。这里面涉及到几部分内容:
     1.工厂类:负责创建具体类实例
     2.抽象类 :所有具体类的抽象父类,可以是接口,也可以是普通类,更可以是抽象类
     3.具体类 :抽象类的具体实现类,一般有多个。

    采用简单工厂模式的初衷是要把client端从对类的实例化中解放出来(对其隐藏具体类的实例化过程),而有专门的工厂类负责所有的具体类得实例化,而具体要实例化哪个类,则有传递的参数决定。
     这样做的好处很明显:
    1.对于经常要变化的内容进行封装,便于维护(封装变化点原则)
    2.把Client于具体类隔离,降低耦合。

    有例为证:
Example   数据库变化是经常发生的事情(原来用sql server,现在用oracle。暂时不说多数据库并存的情况,那会有另外更好的模式进行解决),如果按照通常的逻辑,我们都会写sql server数据访问类,而后在client端涉及到数据访问的地方,就对此数据访问类实例化,并做具体的动作。加入哪天要升级数据库到oracle,那么这个设计带来的将是一场噩梦:改写数据访问类,然后凡应用到此类的client均要修改.
    
    采用简单工厂模式,可以有效脱离这种困境:
工厂类:
public class DBFactory
{
    
public DBFactory()
    
{
        
//
        
// TODO: 在此加入建構函式的程式碼
        
//
    }

    
public static DBDAL getDal(string dbtype)
    
{
        DBDAL cDal 
= null;
        
if (dbtype == "Oracle")
        
{
            cDal 
= new OraDAL();
        }

        
else if(dbtype=="SQLServer")
        
{
            cDal 
= new SQLDAL();
        }

        
return cDal;
 
    }

}
抽象类:
public abstract class DBDAL
{
    
public DBDAL()
    
{
        
//
        
// TODO: 在此加入建構函式的程式碼
        
//
    }

    
public abstract DataSet getDs();

}
实现类:SQLDAL
public class SQLDAL : DBDAL
{
    
string connstr = ConfigurationManager.AppSettings["SQLServer"].ToString();

    
public SQLDAL()
    
{
        
//
        
// TODO: 在此加入建構函式的程式碼
        
//
    }


    
public override  DataSet getDs()
    
{
        
using (SqlConnection conn = new SqlConnection(connstr))
        
{
            conn.Open();
            
string sql = "select * from mis";
            SqlDataAdapter ada 
= new SqlDataAdapter(sql,conn);
            DataSet ds 
= new DataSet();
            ada.Fill(ds);
            
return ds;
        }

    }

}
具体类:OraDAL:
public class OraDAL : DBDAL
{
   
    
public OraDAL()
    
{
        
//
        
// TODO: 在此加入建構函式的程式碼
        
//
    }

    
public override DataSet getDs()
    
{
        
string sql = "select * from ivan_test ";
        ISDApp01.ISDApp01 isd01 
= new ISDApp01.ISDApp01();
        DataSet ds 
= isd01.ExecuteQuery(sql);
        
return ds;
    }

}
当然还可以对access,xml进行封装。
Client:
 protected void btnShow_Click(object sender, EventArgs e)
    
{
        
string dbtype = ConfigurationManager.AppSettings["DbType"].ToString();
        DBDAL cDal 
= DBFactory.getDal(dbtype);
        DataSet ds 
= cDal.getDs();
        gvshow.DataSource 
= ds.Tables[0];
        gvshow.DataBind();
    }

需要说明的是,工厂类实现哪个类,是有client传递的dbtype参数决定的,而通常我们可以把它配置在web.config中,便于维护。
<appSettings>
        
<add key="DbType" value="SQLServer"/>
        
<add key="SQLServer" value="server=.;database=MIS;uid=sa;pwd=MIS>
        <add key="
Oracle" value="Data source=oratest;uid=ivan;password=ivan"/>
    
</appSettings>



    可以发现,上述工厂类对具体类的实现,是通过判断参数来进行区别的,虽然看起来有些不雅,但通常可以解决很多的问题。随后读得抽象工厂模式,利用发射机制可能可以有效的解决这个问题。

      【实践】
      WMS系统中的入库作业很多的movement Type,不同的mvt在抛转ERP时要调用不同的RFC或者进行很多不同的操作。并且,实践证明,mvt的增加/减少在无休止的进行...这样,我们必须把这个抛转的动作进行抽象封装,使得这个变化点易于维护和扩展。
      

 


      如图所示:根据不同的MVT,执行不同的动作
      此为一个简单的应用Demo.

SourceCode:/Files/Ivan-Yan/SimpleFactoryPattern.rar


    参考文章:http://www.cnblogs.com/bit-sand/archive/2008/01/25/1053207.html
                   大话设计模式

 

posted on 2008-07-17 14:33  easy2Dev  阅读(350)  评论(0)    收藏  举报

导航