设计模式(四):代理模式

  Head Fisrt设计模式上面有一句话:代理模式要做的:控制和管理访问。代理类似于明星的经纪人,可以处理来访的需求,但不影响明星本人的行为。

  下面的例子,TV是对电视的操作,有channel表示当前的频道,power表示电视电源开关。通过proxy代理,可以记录曾经的操作,如打开的次数,转频道的次数等。

import random
import unittest


class TV(object):
    """docstring for TV"""
    def __init__(self, brand):
        self._brand = brand
        self._channel = None
        self._power = None

    @property 
    def brand( self ):
        return self._brand

    @property
    def channel( self ):
        return self._channel

    @channel.setter
    def channel( self, value ):
        self._channel = value

    

    def power( self ):
        if "on" == self._power:
            self._power = "off"
        else:
            self._power = "on"

    def showPower( self ):
        return self._power




class TestTvClass( unittest.TestCase ):
    """docstring for TestBasicClass"""
    
    def setUp( self ):
        self._tv = TV( "Apple" )

    def test_tv_class_has_attribute( self ):
        self.assertTrue( hasattr( self._tv, 'brand' ) )
        self.assertTrue( hasattr( self._tv, 'channel' ) )
        self.assertTrue( hasattr( self._tv, 'power' ) )
        self.assertTrue( hasattr( self._tv, 'showPower' ) )

    def test_tv_initiate_state( self ):
        self.assertEqual( 'Apple', self._tv.brand )
        self.assertEqual( None, self._tv.showPower() )
        self.assertEqual( None, self._tv.channel )

    def test_turn_on_tv_to_channel_10( self ):
        self._tv.power()
        self._tv.channel = 10

        self.assertEqual( 'on', self._tv.showPower() )
        self.assertEqual( 10, self._tv.channel )

    def test_turn_off_tv( self ):
        self._tv.power()
        self._tv.channel = 10
        self._tv.power()

        self.assertEqual( 'off', self._tv.showPower() )
        self.assertEqual( 10, self._tv.channel )

    def tearDown( self ):
        pass


class Proxy(object):
    """docstring for Proxy"""
    def __init__(self, tv_object):

        self._records = []
        self._obj = tv_object

    def __setattr__( self, attrname, value ):
        if '_' == attrname[0]:
            object.__setattr__( self, attrname, value )
        else:
            self._records.append( attrname )
            self._obj.__setattr__( attrname, value ) 

    def __getattr__( self, attrname ):
        if '_' == attrname[0]:
            return object.__getattribute__( self, attrname )
        else:
            self._records.append( attrname )
            return self._obj.__getattribute__( attrname )

    def showRecord( self ):
        return self._records

    def number_of_operate( self, attrname ):
        return self._records.count( attrname )
        

class TestProxy( unittest.TestCase ):
    """docstring for TestProxy"""
    def setUp( self ):
        self._tv = Proxy( TV( "Apple" ) )

    def test_proxy_has_attribute( self ):
        self.assertTrue( hasattr( self._tv, 'showRecord' ) )

    def test_handle_property_from_proxy_to_tv( self ):
        self._tv.power()
        self._tv.channel = 10
        self.assertEqual( 10, self._tv.channel )
        self.assertEqual( 'on', self._tv.showPower() )

    def test_get_operate_tv_record( self ):
        self._tv.power()
        self._tv.channel = 20

        self.assertEqual( ['power', 'channel'], self._tv.showRecord() )
        self.assertEqual( 20, self._tv.channel )

    def test_get_operate_number( self ):
        self._tv.power()
        self._tv.channel = 10

        self.assertEqual( 1, self._tv.number_of_operate( 'power' ) )
        self.assertEqual( 1, self._tv.number_of_operate( 'channel' ) )



if __name__ == '__main__':
    unittest.main()

   下面是C++实现的一个虚代理的例子:如果直接打开一个图片,所花费的代价会比较大,那么,只要设定一个代理,用户先快速打开代理。然后等需要的时候再打开真正的图片。

View Code
#include <iostream>
#include <string>

using namespace std;

class Image
{
public:
    Image( string name ) : m_imageName( name ){}
    virtual ~Image(){}
    virtual void Show(){}

protected:
    string m_imageName;
    /* data */
};

class BigImage : public Image
{
public:
    BigImage( string name ) : Image( name ){}
    ~BigImage(){}
    void Show() 
    { 
        cout << "Show big image." << m_imageName << endl; 
    }

    /* data */
};

class BigImageProxy : public Image
{
public:
    BigImageProxy( string name ) : Image( name ), m_bigImage( 0 ) {}
    ~BigImageProxy(){ delete m_bigImage; }

    void Show()
    {
        if ( NULL == m_bigImage )
        {
            m_bigImage = new BigImage( m_imageName );
        }
        m_bigImage->Show();
    }

    /* data */
private:
    BigImage *m_bigImage;
};




int main()
{
    Image *image = new BigImageProxy( "proxy.jpg" );
    image->Show();
    delete image;
    return 0;
}

 

posted @ 2013-04-07 21:29  brackenbo  阅读(207)  评论(0编辑  收藏  举报