打造山寨产品和伪造产品的利器——装饰模式

2023-05-16

【文章标题】打造山寨产品和伪造产品的利器——装饰模式

【文章作者】曾健生

【作者邮箱】zengjiansheng1@126.com

【作者QQ190678908

【作者博客】http://blog.csdn.net/newjueqi

                     http://newjueqi.iteye.com/

【编程环境】JDK 1.6.0_01

【作者声明】欢迎转载文章,但转载请保留文章的完整性以及注明文章的出处。

 

*******************************************************************************

       现在“山寨文化”和“伪造产品”大行其道,“山寨春晚”“山寨明星”“山寨手机”等等,“伪造产品”就更加不用说了,广大群众也深受其害(本人也是其中一位受害者!!!)不说不知道,在学设计模式的过程中本人一不小心发现了装饰模式是有很强的“伪造功能”(“伪造功能”是指把别人写的类,功能模块等包装一下换成自己写的,但其实核心还是别人写的代码)和“山寨功能”(利用类提供的接口添加代码增强类的功能)。

    《设计模式:可复用面向对象软件的基础》是这样定义装饰模式(Decorator):动态地给一个对象添加一些额外的职责,就增加功能来来说,装饰模式比生成子类更加灵活。

       一般来说,实现装饰器模式可分为下面3步:

1. 建立包装类,定义构造函数接收包装对象

2. 建立成员引用,让被包装对象作用于整个包装类

3.根据需要增加一些功能函数已增强类的功能

 

如果我们把装饰器模式实现“伪造功能”,就分为以下3步(非常邪恶的!!!):

1. 建立包装类,定义构造函数接收包装对象的参数

2. 建立成员引用,让被包装对象作用于整个包装类

3. 用自定义的函数封装包装对象的函数

 

以前有个著名的“汉芯造假”事件,大概就是说把某个外国芯片的标识去掉,然后改头换面,就变成了所谓的“汉芯”了。用装饰器模式实现“伪造功能”模拟这个过程的代码如下:

 

//一个美国芯片类,这个芯片类有三个功能:

//1.显示自身的信息

//2.获得两个数相加的结果

//3.获得两个数相减的结果

class AmericanChip

{    

       //美国芯片类的构造函数

       AmericanChip( ){}

      

       //美国芯片类显示自身信息的函数

       public void printInfo()

       {

              System.out.println( "我是美国的芯片" );

       }

      

       //获得两个数相加的结果

       public double add( double x, double y )

       {

              return x+y;

       }

      

       //获得两个数相减的结果

       public double sub( double x, double y  )

       {

              return x-y;

       }    

}

 

//这是造假芯片类,把美国的芯片改头换面后完成的

//步骤分为三步:

//1.建立包装类,定义构造函数接收包装对象的参数

//2.建立成员引用,让被包装对象作用于整个包装类

//3.用自定义的函数封装包装对象的函数

class FakeChip

{

       //建立被包装类的引用

       private AmericanChip americanChip;

      

       FakeChip(  )

       {

              //构造美国的芯片类的实例

              this.americanChip=new AmericanChip();

       }

      

       //造假芯片类显示自身信息的函数,这个函数就相同于把美国芯片的标识去掉,换上“汉芯”的标识

       public void printInfoFake()

       {

              System.out.println( "我是造假芯片" );

       }

      

       //造假芯片类通过美国芯片类获得两个数相加的结果

       public double addFake( double x, double y )

       {

              return americanChip.add( x, y );  

       }

                           

       //造假芯片类通过美国芯片类获得两个数相减的结果

       public double subFake( double x, double y  )

       {

              return americanChip.sub( x, y );

 

       }

      

}

 

造假芯片类FakeChip共暴露了3个接口:

1. public void printInfoFake()

2. public double addFake( double x, double y )

3. public double subFake( double x, double y  )

 

       从代码可看出,除了printInfoFake()方法是显示自身的信息外(造假产品要先显示一下自身的产品信息使别人误认为是正牌货),其他的两个方法addFakehe subFake实际上是调用了美国芯片类的相关方法,这就模拟了“汉芯”造假的过程。

       可能有的读者可能问使用继承不是能实现这个结果吗?选用装饰器模式而不用继承有两个原因:

1.       装饰器模式可选择需要暴露被包装类(美国芯片类AmericanChip)的哪些公有函数,虽然也可以用继承后覆盖同名函数的方法实现,但如果包装类(美国芯片类AmericanChip)的公有函数非常多的话,那真的写代码写得人崩溃!!!

2.       可把被包装类(美国芯片类AmericanChip)的公有函数用间接实现改名调用,真正实现改头换面的目的。

 

虽然本文前面论述的内容是怎么用装饰器模式实现“造假”过程,但我们必须要明白一个事实:装饰器模式的出现是为了给子类添加新的功能提供方便性和灵活性,这个才是装饰器模式的最主要用途。

javaIO类中有个类FileInputStream用来处理文件数据的,另外还有一个类BufferedInputStream提供了缓冲区的功能,大家认真比较一下BufferedInputStreamFileInputStream的函数,发现多了缓冲的功能外,其他的实现都是很相近的,另外查找一下BufferedInputStream的构造函数BufferedInputStream(InputStream in),能发现BufferedInputStream的实例化是传入了InputStream的对象,大家有没有发现和前面论述的实现装饰器模式的三步非常像,虽然在源码里BufferedInputStream的实现比较麻烦,但我们可用装饰器模式的思想,实现一个“山寨版BufferedInputStream”类。

 

 

//这是山寨版的BufferedInputStreamMyBufferedInputStream

 

package newjueqi.net.csdn.MyBufferedInputStream;

 

//这是山寨版的BufferedInputStreamMyBufferedInputStream

 

import java.io.*;

class MyBufferedInputStream

{

    private int num=0;//读入字节的个数

    private int pos=0;//当前在数组中的下标

   

    //实现装饰器模式步骤2:建立成员引用,让被包装对象作用于整个包装类

    private InputStream inputstream_temp=null; //字节流的引用

   

    private byte buf[]=new byte[1024]; //缓冲区数组

    byte temp=0;

   

    //实现装饰器模式步骤1:建立包装类,定义构造函数接收包装对象

    MyBufferedInputStream( InputStream inputstream_temp )

    {

       this.inputstream_temp=inputstream_temp;

    }

   

    //实现装饰器模式步骤3:根据需要增加一些功能函数已增强类的功能

    //用缓冲区增强了读取的功能

    public int myRead()

    {

       //把缓冲区的数据填满

       if( num==0 )

       {

           try {

              //num中保存了读入缓冲区的字节的个数

              num=inputstream_temp.read(buf);

              pos=0;

             

              //表示已读到文件尾,返回-1

              if( num<0 )

                  return -1;

              temp=buf[pos];

              num--;

              pos++;

             

              //为了防止读入数据如果为11111111后类型转换后变成

              //-1,所以要把多余位上的1去掉用&运算

              return temp&0xff;

           } catch (IOException e) {

              // TODO Auto-generated catch block

              e.printStackTrace();

              return -1;

           }         

       }

       else if( num>0 )  //取出缓冲区中的数据

       {

           temp=buf[pos];

           num--;

           pos++;

           return temp&0xff;

       }

       return -1;

    }

   

    //关闭字节流

    public void close()

    {

       try {

           inputstream_temp.close();

       } catch (IOException e) {

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

打造山寨产品和伪造产品的利器——装饰模式 的相关文章

随机推荐