zoukankan      html  css  js  c++  java
  • Castle与Mixin

            Mixin是一种将某个类中的方法混入其他类中的软件开发风格。简单的说,就是一个类可以使用其他类的方法。这个初听起来有点像类的继承,但是这与传统的类继承的方式不一样。
            首先,Mixin不是类的继承。传统的,一个类A继承了某个类B,那么A就可以直接调用B中的非private的方法。但是在Mixin中,A与B没有继承关系,而A却能使用B的非private的方法。
            其次,Mixin的这些行为是在运行时发生的,而不是静态指定的。

            下面是一个来自Python的Mixin的例子:
    John 翻著新的一期 LJ(Linux Journal) 

    [John@mars /tmp]# vi Lover.py 

    class lover:
        def __init__(self,man='man',woman='woman'):
            self.lover='When a '+man+' love a '+woman
            print self.lover
        def smile(self):
            print self.lover+':-)'
        def kiss(self):
            print self.lover+':-)(-:'


    [John@mars /tmp]# python
    Python 2.1 (#1, Apr 18 2001, 17:55:45)
    [GCC 2.95.3 19991030 (prerelease)] on linux2
    Type "copyright", "credits" or "license" for more information.

    >>>from Lover import lover

    >>>John_and_Rose=lover()
    When a man love a woman

    >>>John_and_Rose.smile()
    when a man love a woman:-)

    >>>John_and_Rose.kiss()
    when a man love a woman:-)(-:

    >>>John_and_Rose.sayGoodBye()
    Traceback (most recent call last):
      File "", line 1, in ?
    AttributeError: lover instance has no attribute 'sayGoodBye'

    >>>John_and_rose.JohnAskWhy()
    Traceback (most recent call last):
      File "", line 1, in ?
    AttributeError: lover instance has no attribute 'JohnAskWhy'

    >>>class RoseLoveSomebodyElse:
       def sayGoodBye(self):
           print "Let's say goodbye tonight."

    >>>lover.__bases__+=(RoseLoveSomebodyElse,)

    >>>John_and_Rose.sayGoodBye()
    Let's say goodbye tonight.
    >>>

    练习完 Using Mix-ins with Python 之後, 
    John 在闪著 >>> 的萤幕前大声地哭了起来。 

            注意,Python代码中的class RoseLoveSomebodyElse之后的代码,John定义了一个类,并将这个类与lover执行了Mixin,之后,lover具备了sayGoodBye的能力。
            这就是Mixin的威力。
            在学习Castle中,我发现Castle也具有Mixin的能力,所以,我模仿上面Python的例子,利用Castle尝试了Mixin。
            当然,C#不能像Python那样动态的执行以及支持多重继承,因此,我对上面的代码作了改动,使之适应C#。

            首先,我定义了一个类Lover及其接口ILover:
    public interface ILover
    {
        
    void Smile();
        
    void Kiss();
        
    void SayGoodbye2Lover();
    }


    public class Lover:ILover
    {
        
    private string _Lover = "";
        
        
    public Lover(string man, string woman)
        
    {
            _Lover 
    = "When " + man + " love " + woman;
            WL(_Lover);
        }

        
        
    public void Smile()
        
    {
            WL(_Lover 
    + " :-)");
        }

        
        
    public void Kiss()
        
    {
            WL(_Lover 
    + " :-)(-:");
        }

        
        
    public void SayGoodbye2Lover()
        
    {
            
    throw new System.NotSupportedException("We can not Say Goodbye");
        }

    }

            与Python代码不同的是,我多增加了一个SayGoodbye2Lover的方法。

            然后,我再定义了一个LoverLoveSomebodyElse及其接口ILoverLoveSomebodyElse,这个类对应Python例子中的RoseLoveSomebodyElse类。
    public interface ILoverLoveSomebodyElse
    {
        
    void LoverChangedMind(string who, string somebody);
        
    void SayGoodbye();
    }


    public class LoverLoveSomebodyElse:ILoverLoveSomebodyElse
    {
        
    private string _Who;
        
    private string _Somebody;
        
        
    public LoverLoveSomebodyElse()
        
    {
        }

        
        
    public void LoverChangedMind(string who, string somebody)
        
    {
            _Who 
    = who;
            _Somebody 
    = somebody;
        }

        
        
    public void SayGoodbye()
        
    {
            WL(_Who 
    + " changed mind and loved " + _Somebody);
            WL(
    "So ");
            WL(
    "Let's say goodbye tonight");
        }

    }

            随后,定义了一个Matchmaker类,这只是一个普通的类,不起任何作用。主要是为了创建代理用。
    public class Matchmaker
    {
        
    public Matchmaker()
        
    {
        }

        
        
    public virtual void Match()
        
    {
        }

    }

            好了,现在可以利用这三个类测试Mixin。这里主要对两个类测试Mixin:Lover和LoverLoveSomebodyElse

            在执行函数中输入如下代码:
    public static void Main()
    {
        
    try
        
    {
            WL(Environment.CurrentDirectory);
            GeneratorContext context 
    = new GeneratorContext();
            Lover lover 
    = new Lover("Wu Da Lang""Qin Xiang Lian");
            LoverLoveSomebodyElse changedMindLover 
    = new LoverLoveSomebodyElse();
            context.AddMixinInstance(changedMindLover);
            context.AddMixinInstance(lover);
                
            ProxyGenerator _generator 
    = new ProxyGenerator();
            
    object proxy = _generator.CreateCustomClassProxy(typeof(Matchmaker), new StandardInterceptor(), context);
                
            ILover lover_now 
    = proxy as ILover;
            lover_now.Smile();
            lover_now.Kiss();
                
            
    try
            
    {
                lover.SayGoodbye2Lover();
            }

            
    catch(System.NotSupportedException eX)
            
    {
                WL(eX.Message);
            }

                
            ILoverLoveSomebodyElse changedMindLover_now 
    = proxy as ILoverLoveSomebodyElse;
            changedMindLover_now.LoverChangedMind(
    "Pan Jin Lian""Xi Men Qing");
            changedMindLover_now.SayGoodbye();
        }

        
    catch(Exception eX)
        
    {
            WL(eX.Message);
            WL(eX.StackTrace);
        }

            
        RL();
    }

            执行后的结果如下:
    When Wu Da Lang love Pan Jin Lian
    When Wu Da Lang love Pan Jin Lian :-)
    When Wu Da Lang love Pan Jin Lian :-)(-:
    We can not Say Goodbye
    Pan Jin Lian changed mind and loved Xi Men Qing
    So 
    Let's say goodbye tonight

           就这样,proxy具备了Lover和LoverLoveSomebodyElse的所有可用的功能。

           很显然,从代码中可以看出,如果proxy是一个代码级的类的话,那么proxy继承了ILover和ILoverLoveSomebodyElse两个接口。正如我们在传统的给一个类添加行为的方法一样。

           例如,有一个类Foo,它只有一个方法:WriteMessage。如果我们想给Foo添加一个可选的Log行为,我们可以定义一个接口ILog,并给让Foo继承ILog,这样,Foo就变成了LoggableFoo了。

           Castle正是这样的做的。如我的另一篇Castle与动态代理中所说的,Castle创建一个类,这个类继承了ILover和ILoverLoveSomebodyElse接口,并使用Interceptor和Invocation织入Lover和LoverLoveSomebodyElse类的方法,从而使Proxy具备了两者的方法。

            使用Mixin可以让我们动态的决定哪些类在运行时可以具备哪些可选的功能。当然,由于C#不支持类多重继承,因此,我们必须要把能够Mixin的类抽象出接口。
  • 相关阅读:
    LeetCode Best Time to Buy and Sell Stock
    LeetCode Scramble String
    LeetCode Search in Rotated Sorted Array II
    LeetCode Gas Station
    LeetCode Insertion Sort List
    LeetCode Maximal Rectangle
    Oracle procedure
    浏览器下载代码
    Shell check IP
    KVM- 存储池配置
  • 原文地址:https://www.cnblogs.com/iaxes/p/133407.html
Copyright © 2011-2022 走看看