我也设计模式——13.Decorator



代码实现如下,注意几点:
1.Decorator中的Operation()方法是对被修饰对象ConcreteComponent中方法Operation()的封装
2.ConcreteDecorator中的Operation()方法是对其父类Operation()方法的封装,同时加入一些额外的新方法
3.ConcreteDecorator中的构造函数负责将修饰与被修饰对象链接在一起,如下图:

    public interface Component
    
{
        
void Operation();
    }


    
public class ConcreteComponent : Component
    
{
        
public void Operation()
        
{
            Console.WriteLine(
"Old Function");
        }

    }


    
public class Decorator : Component
    
{
        
protected Component op;

        
public virtual void Operation()
        
{
            op.Operation();
        }

    }


    
public class ConcreteDecoratorA : Decorator
    
{
        
public ConcreteDecoratorA(Component op)
        
{
            
this.op = op;
        }


        
private void DoSomeThing1()
        
{
            Console.WriteLine(
"New Function 1");
        }



        
public override void Operation()
        
{
            op
.Operation();
            DoSomeThing1();
        }

    }


    
public class ConcreteDecoratorB : Decorator
    
{
         
public ConcreteDecoratorB(Component op)
        
{
            
this.op = op;
        }


        
private void DoSomeThing2() 
        
{
            Console.WriteLine(
"New Function 2");
        }


        
public override void Operation()
        
{
            
base.Operation();
            DoSomeThing2();
        }


    }


    
public class Client
    
{
        
public static void Main(string[] args)
        
{
            ConcreteComponent c 
= new ConcreteComponent();
            ConcreteDecoratorA d1 
= new ConcreteDecoratorA(c);
            ConcreteDecoratorB d2 
= new ConcreteDecoratorB(d1);           

            d2.Operation();
        }

    }

装饰者与被装饰者具有相同的接口,从而动态增加的功能不会破坏已有的接口,即修有一个对象后,其接口不发生变化
透明且动态的方式增加单个对象的功能
所谓透明,即用户仍可以直接访问被修饰者
另外一种增加功能的方法是继承
使用时保持被修饰者的功能单一,从而进行修饰的时候,可以组合出更多的功能,结构灵活——即被修饰者“原子化”

Decorator的缺点是会产生许多小对象。

可以使用Decorator来给抽象工厂增加新方法,以为DB增加记录日志功能为例:

LogDB是这么写的:
    public class LogDB : clsAbstractDB
    
{
        
private clsAbstractDB myDB;

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


        
public override void Open()
        
{
            myDB.Open();
            Record(
"
Open");
        }


        
public override DataTable ExecSQL(string strSQL)
        
{
            DataTable dt 
= myDB.ExecSQL(strSQL);
            Record(
"ExecSQL: " + strSQL);

              return dt;
        }


        
//新方法 记录日志
        private void Record(string strRecord)
        

            
//再次记录日志
        }

    }

经典的BufferStream:


由于在.NET中已经实现了框架,我们只看怎么使用:
Buffered的作用是为另一流上的读写操作添加一个缓冲层,从而提高读取和写入性能
        public void BufferedStreamMethod(string path)
        
{
            FileStream fs 
= File.Create(path);
            Stream bs 
= new BufferedStream(fs);

            AddText(bs, 
"Hello!");
        }


        
public void AddText(Stream fs, string value)
        
{
            
byte[] info = new UTF8Encoding(true).GetBytes(value);
            fs.Write(info, 
0, info.Length);
        }

装饰模式与策略模式,两者能达到同样的效果——增加新功能,对比以下UML图,
    

    二者的不同是,Decorator是从小到大,层层包装;Strategy是先制作大粒度对象,其中包括不变的对象和可变的部分。

微软的AJAX.NET控件是基于Decorator实现的,原来的TextBox等基本控件仍然可以使用,然而我们可以使用新的控件绑定到这个TextBox上,从而增加新的功能。
posted @ 2007-10-02 21:21  包建强  Views(670)  Comments(0Edit  收藏  举报