williambirkin

恭喜发财!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

意图
不使用创建子类的方法动态的增加类的功能。

结构




模式的参与者如下:
Compeonent:定义一个对象接口,可以动态添加这些对象的功能。
ConcreteComponent:定义一个对象,可以动态的为其添加一些功能。
Decorator:维持一个对Component对象的引用,并定义与Component接口的一致接口。
ConcreteDecorator:为组件添加功能。

下面举的是一个为数据访问类添加日志功能的例子。
数据访问类包括支持SQLServer、Oracle和OLE三种类型的数据库访问的类。现在需要在数据库访问类的基础上增加记录数据库操作的日志功能。日志的记录方式可以是关系数据库或文件形式。

数据库访问类的抽象类:定义一个对象接口,可以动态添加这些对象的功能。

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace DecoratorPattern.ex3
{
    
public abstract class clsAbstractDB
    
{
        
private string _connString;

        
public string ConnString
        
{
            
get return _connString; }
            
set { _connString = value; }
        }


        
public clsAbstractDB()
        
{
            _connString 
= "";
        }


        
public clsAbstractDB(string connstr)
        
{
            _connString 
= connstr;
        }


        
public abstract void Open();
        
public abstract void Close();
        
public abstract DataSet ExecSQL(string strSQL);
        
public abstract void ExecSQLNonQuery(string strSQL);
    }

}


SQLServer的数据库访问类

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace DecoratorPattern.ex3
{
    
public class clsSQLServerDB:clsAbstractDB
    
{
        
public override void Open()
        
{
            Console.WriteLine(
"clsSQLServerDB.Open");
        }


        
public override void Close()
        
{
            Console.WriteLine(
"clsSQLServerDB.Close");
        }


        
public override System.Data.DataSet ExecSQL(string strSQL)
        
{
            DataSet ds 
= new DataSet();
            Console.WriteLine(
"clsSQLServerDB.ExecSQL:" + strSQL);
            
return ds;
        }


        
public override void ExecSQLNonQuery(string strSQL)
        
{
            Console.WriteLine(
"clsSQLServerDB.ExecSQLNonQuery" + strSQL);
        }

    }

}

Oracle的数据库访问类

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace DecoratorPattern.ex3
{
    
public class clsOracleDB : clsAbstractDB
    
{
        
public override void Open()
        
{
            Console.WriteLine(
"clsOracleDB.Open");
        }


        
public override void Close()
        
{
            Console.WriteLine(
"clsOracleDB.Close");
        }


        
public override System.Data.DataSet ExecSQL(string strSQL)
        
{
            DataSet ds 
= new DataSet();
            Console.WriteLine(
"clsOracleDB.ExecSQL:" + strSQL);
            
return ds;
        }


        
public override void ExecSQLNonQuery(string strSQL)
        
{
            Console.WriteLine(
"clsOracleDB.ExecSQLNonQuery" + strSQL);
        }

    }

}


OLE的数据库访问类

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace DecoratorPattern.ex3
{
    
public class clsOLEDB : clsAbstractDB
    
{
        
public override void Open()
        
{
            Console.WriteLine(
"clsOLEDB.Open");
        }


        
public override void Close()
        
{
            Console.WriteLine(
"clsOLEDB.Close");
        }


        
public override System.Data.DataSet ExecSQL(string strSQL)
        
{
            DataSet ds 
= new DataSet();
            Console.WriteLine(
"clsOLEDB.ExecSQL:" + strSQL);
            
return ds;
        }


        
public override void ExecSQLNonQuery(string strSQL)
        
{
            Console.WriteLine(
"clsOLEDB.ExecSQLNonQuery" + strSQL);
        }

    }

}


实现功能扩展的接口。

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace DecoratorPattern.ex3
{
    
public abstract class Log : clsAbstractDB
    
{
        
private clsAbstractDB _myDB;

        
public clsAbstractDB DB
        
{
            
get return _myDB;}
            
set { _myDB=value;}
        }


        
public Log(clsAbstractDB mydb)
        
{
            
this._myDB = mydb;
        }


        
public override void Open()
        
{
            _myDB.Open();
            WriteLog(GetmyDBType() 
+ " Open");
        }


        
public override void Close()
        
{
            _myDB.Close();
            WriteLog(GetmyDBType() 
+ " Close");
        }


        
public override DataSet ExecSQL(string strSQL)
        
{
            DataSet ds
=_myDB.ExecSQL(strSQL);
            WriteLog(GetmyDBType() 
+ " ExecSQL");
            
return ds;
        }


        
public override void ExecSQLNonQuery(string strSQL)
        
{
            _myDB.ExecSQLNonQuery(strSQL);
            WriteLog(GetmyDBType() 
+ " ExecSQLNonQuery");
        }


        
public abstract void WriteLog(string str);

        
private string GetmyDBType()
        
{
            Type t
=_myDB.GetType();

            
return t.FullName;
        }

    }

}


支持关系数据库的日志功能的类。

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace DecoratorPattern.ex3
{
    
public class LogDB : Log
    
{
        
public LogDB(clsAbstractDB mydb):base(mydb)
        
{
            
base.DB = mydb;
        }


        
public override void Open()
        
{
            
base.Open();
        }


        
public override void Close()
        
{
            
base.Open();
        }


        
public override System.Data.DataSet ExecSQL(string strSQL)
        
{
            
return base.ExecSQL(strSQL);
        }


        
public override void ExecSQLNonQuery(string strSQL)
        
{
            
base.ExecSQLNonQuery(strSQL);
        }


        
public override void WriteLog(string str)
        
{
            Console.WriteLine(
"LogDB.WriteLog:" + str);
            Console.WriteLine(
"");
        }

    }

}


支持XML文件的日志功能的类。

using System;
using System.Collections.Generic;
using System.Text;

namespace DecoratorPattern.ex3
{
    
public class LogXml : Log
    
{
        
public LogXml(clsAbstractDB mydb)
            : 
base(mydb)
        
{
            
base.DB = mydb;
        }


        
public override void Open()
        
{
            
base.Open();
        }


        
public override void Close()
        
{
            
base.Open();
        }


        
public override System.Data.DataSet ExecSQL(string strSQL)
        
{
            
return base.ExecSQL(strSQL);
        }


        
public override void ExecSQLNonQuery(string strSQL)
        
{
            
base.ExecSQLNonQuery(strSQL);
        }


        
public override void WriteLog(string str)
        
{
            Console.WriteLine(
"LogXml.WriteLog:" + str);
            Console.WriteLine(
"");
        }

    }

}


获得具体类型的工厂

using System;
using System.Configuration;
using System.Collections.Generic;
using System.Text;

namespace DecoratorPattern.ex3
{
    
public class clsCreateDB
    
{
        
public static clsAbstractDB CreateDB()
        
{
            clsAbstractDB clsDB;
            
string strType = ConfigurationManager.AppSettings["strDBType"];
            
string strConn = ConfigurationManager.AppSettings["strConn"];

            
switch(strType)
            
{
                
case "clsSQLServerDB":
                    clsDB 
= new clsSQLServerDB(strConn);
                    
break;
                
case "clsOLEDB":
                    clsDB 
= new clsOLEDB(strConn);
                    
break;
                
case "clsOracleDB":
                    clsDB 
= new clsOracleDB(strConn);
                    
break;
                
default:
                    clsDB 
= null;
                    
break;
            }


            
return clsDB;
        }


        
public static Log CreateLog(clsAbstractDB DB)
        
{
            Log log;
            
string strLogType = ConfigurationManager.AppSettings["strLogType"];

            
switch (strLogType)
            
{
                
case "LogDB":
                    log 
= new LogDB(DB);
                    
break;
                
case "LogXml":
                    log 
= new LogXml(DB);
                    
break;
                
default:
                    log 
= null;
                    
break;
            }


            
return log;
        }

    }

}


使用的代码

        private static void Main(string[] args)        {            
            ex3.clsAbstractDB db 
= ex3.clsCreateDB.CreateDB();
            
//实现日志功能的扩展
            ex3.Log log = ex3.clsCreateDB.CreateLog(db);
            log.Open();
            DataSet ds
=log.ExecSQL("select * from customers");
            log.ExecSQLNonQuery(
"select * from customers");
            log.Close();
        }



适用性
(1)在不影响其它对象的情况下,以动态且透明的方式添加单个对象的功能。
(2)处理那些可以撤销的功能。
(3)不能生成子类的方法扩充时。


效果
Decorator模式的优点是提供了比继承更加灵活的扩展,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。
由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。


BufferStream——.NET中的装饰模式
.NET中Decorator模式一个典型的运用就是关于Stream,它存在着如下的类结构:



可以看到, BufferedStream和CryptoStream其实就是两个包装类,这里的Decorator模式省略了抽象装饰角色(Decorator),示例代码如下:

class Program
{
    
public static void Main(string[] args)
    
{

        MemoryStream ms 
=

            
new MemoryStream(new byte[] 100,456,864,222,567});

 

        
//扩展了缓冲的功能

        BufferedStream buff 
= new BufferedStream(ms);

 

        
//扩展了缓冲,加密的功能

        CryptoStream crypto 
= new CryptoStream(buff);

    }

}

改变外观还是改变内核
从适应对象变化的角度看,有两种方法可以达到目的,一种方法是制作一个小粒度的内核对象,然后进行包装,这是装饰模式实现的方法;另一种方法是制作一个大粒度的对象,其中包括不可变的部分和可变的部分,可变的部分可以采用策略模式实现。
posted on 2007-01-24 10:02  williambirkin  阅读(305)  评论(0编辑  收藏  举报