zoukankan      html  css  js  c++  java
  • 装饰者模式

        解决的问题是:我有一个类A,里面可能须要非常多不同行为的功能。

        如今有三种解决方法,第一种:每一个功能都弄成一个类,然后继承类A,这样的的问题是,假设功能非常多,会造成类爆炸。

        另外一种:我将功能类组合上类A上,这样的想法是好的,但还没够弹性,由于这样我没法在不改动类A的情况下对功能的动态添删。(我的目的就是在不改动类A的情况下,对类A进行功能扩展)

        第三种:就是我要说的装饰者模式。

        举个样例,我有一个饮品店,我有非常多饮料,也有非常多调料,我通过对饮料搭配不同种类和不同数量的调料,来组合成我的饮品。对吧,由于有非常多种组合,所以这里须要动态组合。

        所以我须要一个被装饰者类(饮料和调料的总类,即须要被装饰的内核类):

    public abstract class Beverage {
    	String description = "Unknown Beverage";
      
    	public String getDescription() {
    		return description;
    	}
     
    	public abstract double cost();
    }
    

        我也须要一个调料的总类(继承被装饰者类,由于我须要调料和饮料的类型同样,等下后面会说):

    public abstract class CondimentDecorator extends Beverage {
    	public abstract String getDescription();
    }
    

        我有非常多饮料类:

    public class Espresso extends Beverage {
      
    	public Espresso() {
    		description = "Espresso";
    	}
      
    	public double cost() {
    		return 1.99;
    	}
    }
    

    public class HouseBlend extends Beverage {
    	public HouseBlend() {
    		description = "House Blend Coffee";
    	}
     
    	public double cost() {
    		return .89;
    	}
    }
    

        我也有调料类:

    public class Mocha extends CondimentDecorator {
    	Beverage beverage;
     
    	public Mocha(Beverage beverage) {
    		this.beverage = beverage;
    	}
     
    	public String getDescription() {
    		return beverage.getDescription() + ", Mocha";
    	}
     
    	public double cost() {
    		return .20 + beverage.cost();
    	}
    }

    public class Whip extends CondimentDecorator {
    	Beverage beverage;
     
    	public Whip(Beverage beverage) {
    		this.beverage = beverage;
    	}
     
    	public String getDescription() {
    		return beverage.getDescription() + ", Whip";
    	}
     
    	public double cost() {
    		return .10 + beverage.cost();
    	}
    }
    

    public class Soy extends CondimentDecorator {
    	Beverage beverage;
    
    	public Soy(Beverage beverage) {
    		this.beverage = beverage;
    	}
    
    	public String getDescription() {
    		return beverage.getDescription() + ", Soy";
    	}
    
    	public double cost() {
    		return .15 + beverage.cost();
    	}
    }
    

        最后我来组合几杯不同的饮品:

    public class StarbuzzCoffee {
     
    	public static void main(String args[]) {
    		Beverage beverage = new Espresso();
    		System.out.println(beverage.getDescription() 
    				+ " $" + beverage.cost());
     
    		Beverage beverage2 = new DarkRoast();
    		beverage2 = new Mocha(beverage2);
    		beverage2 = new Mocha(beverage2);/*这里就解析了为什么我须要饮料和调料同一类型了。如果不同的类型,我如果饮料为A类(被装饰者),调料为B类,我第一次装饰时,我实例化后,那个被装饰者就变成B类型的,我在此基础上再装饰还有一个调料,由于我须要传一个A类型的进去,但我的已经变成B类型了,所以就不能再装饰第二次了。同类型的就解决问题了*/
    		beverage2 = new Whip(beverage2);
    		System.out.println(beverage2.getDescription() 
    				+ " $" + beverage2.cost());
     
    		Beverage beverage3 = new HouseBlend();
    		beverage3 = new Soy(beverage3);
    		beverage3 = new Mocha(beverage3);
    		beverage3 = new Whip(beverage3);
    		System.out.println(beverage3.getDescription() 
    				+ " $" + beverage3.cost());
    	}
    }
    

        看到如今,你应该对装饰者模式有一定了解了,我在弄一种情况来加深你的理解。

        还记得java中的i/o流不,没错,java.io类就是用装饰者模式的。记得大一时初次学java,看i/o流这部分最烦了,也不懂它的原理,它的类也非常多。如今知道它的运作了:

    以InputStream为例,它的“饮料”有FileInputStream,StringBufferInputStream,ByteArrayInputStream,

                                      它的“调料”总类是:FilterInputStream,

                                                        装饰者是:BufferedInputStream,DataInputStream,LineNumberInputStream等。

        我来自己写一个i/o的装饰者类来加深理解吧:

    import java.io.*;
    
    public class LowerCaseInputStream extends FilterInputStream {
    
    	public LowerCaseInputStream(InputStream in) {
    		super(in);
    	}
     
    	public int read() throws IOException {
    		int c = super.read();
    		return (c == -1 ? c : Character.toLowerCase((char)c));
    	}
    		
    	public int read(byte[] b, int offset, int len) throws IOException {
    		int result = super.read(b, offset, len);
    		for (int i = offset; i < offset+result; i++) {
    			b[i] = (byte)Character.toLowerCase((char)b[i]);
    		}
    		return result;
    	}
    }
    

    再来个測试类:

    import java.io.*;
    
    public class InputTest {
    	public static void main(String[] args) throws IOException {
    		int c;
    
    		try {
    			InputStream in = 
    				new LowerCaseInputStream(
    					new BufferedInputStream(
    						new FileInputStream("test.txt")));
    
    			while((c = in.read()) >= 0) {
    				System.out.print((char)c);
    			}
    
    			in.close();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    对吧,是不是非常灵活,自己须要什么条件,写个装饰者类就能够动态改变了。

    很多其它设计模式解说,关注我吧,我会不时地更新,还有我还会发一些其它如java方法、框架、Linux等一些的心得,我会努力成为大神,并帮助大家一起成为大神的。大笑

  • 相关阅读:
    不同等级数据源的多级缓冲环的生成
    从DataTable到List<Model>(C#.net)
    string与char之间的转换以及如何获得string所占位数
    AndroidKotlin
    Android高级POS开发
    IOS 应用开发
    Android切屏的处理
    Android POS开发
    Android深入理解JNI
    Android的IPC机制Binder
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3916467.html
Copyright © 2011-2022 走看看