WS分享10-跟着JDK学设计模式(一)

如果这篇文章对您有些用处,请点赞告诉我O(∩_∩)O

设计模式的文章千千万,其实不用写的太复杂,JDK就是最好sample。他怎么用我们就怎么用。

以下定义均来自《GOF设计模式》

1、SINGLETON(单件)— 对象创建型模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式有很多形式,JDK中Runtime类使用饿汉,简单且安全。

具体步骤:

1、构造方法私有

2、成员变量实例化

3、提供获取实例的方法

public class Runtime {
    private static Runtime currentRuntime = new Runtime();  //2、成员变量实例化

    public static Runtime getRuntime() {  //3、提供获取实例的方法
        return currentRuntime;
    }

    private Runtime() {} //1、构造方法私有
    ....
}

测试:java执行mac上的pwd命令

Runtime runtime = Runtime.getRuntime();
		try (InputStream in = runtime.exec("pwd").getInputStream(); 
				BufferedReader br = new BufferedReader(new InputStreamReader(in));) {
			String line = "";
			while ((line = br.readLine()) != null) {
				System.out.println(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

结果:/Users/yaoguangyao/DEV/EWS-JAVA/tij

 

2.、STRATEGY(策略)— 对象行为型模式

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独 立于使用它的客户而变化。

JDK中Comparable 和 Comparetor使用两种形式的策略模式实现了比较以及排序。

(1)Comparable 目标对象实现算法接口,内置算法

具体步骤:

1、抽象出算法接口

2,使用算法接口

3、目标对象实现算法接口

public interface Comparable<T> { //1、抽象出算法接口
    public int compareTo(T o); //比较算法
}

Collections.sort

public static <T extends Comparable<? super T>> void sort(List<T> list) { 
    list.sort(null); //T必须实现Comparable
}

Collections.sort内部使用TimSort.binarySort 二分排序,在插入排序基础上加入二分思想,每次和中间值比较使用的是compareTo方法。

private static void binarySort(Object[] a, int lo, int hi, int start) {
......
for ( ; start < hi; start++) {
            Comparable pivot = (Comparable) a[start]; //当前值,将当前元素向上转型为Comparable
            ......
            while (left < right) {
                int mid = (left + right) >>> 1; //取中间索引
                if (pivot.compareTo(a[mid]) < 0) //2、使用算法接口:使用Comparable.compareTo方法比较当前值和中间值
                    right = mid;
                else
                    left = mid + 1;
            }
            ......
}

测试:商品按照数量倒序且id正序排序

class Product implements Comparable<Product> {
		private Long id;
		private String name;
		private Integer count; 
            ......
            @Override
		public int compareTo(Product o) { //3、目标对象实现算法接口
			if (o != null) {
				if (this.count > o.count) {
					return -1; // 按照数量倒序
				} else if (this.count < o.count) {
					return 1;
				} else if (this.id > o.id) {
					return 1; // 按照id正序
				} else if (this.id < o.id) {
					return -1;
				} else {
					return 0;
				}
			}
			return 0;
		}
  
		@Override
		public String toString() {
			return "[id:" + id + ", name:" + name + ", count:" + count + "]";
		}
  
           public static void main(String[] args) {
			List<Product> products = new ArrayList<>();
			products.add(new Product(1l, "可乐", 50));
			products.add(new Product(2l, "雪碧", 70));
			products.add(new Product(3l, "酸奶", 70));
			products.add(new Product(4l, "牛奶", 80));
			Collections.sort(products);
			System.out.println(products);
		}
  }

结果:

[[id:4, name:牛奶, count:80], [id:2, name:雪碧, count:70], [id:3, name:酸奶, count:70], [id:1, name:可乐, count:50]]

(2)Comparetor 目标对象无需实现算法接口,外置算法

具体步骤:

1、抽象出算法接口

2、使用外置算法

3、外置算法实现

public interface Comparator<T> { //1、抽象出算法接口
    int compare(T o1, T o2);
    .....
}

Collections.sort

 public static <T> void sort(List<T> list, Comparator<? super T> c) {
        list.sort(c);
    }

Collections.sort(List) 和 Collections.sort(List, Comparator) 区别,在于后者目标对象没有实现算法接口,而是算法外置,同样使用二分排序,每次和中间值比较使用的是Comparator.compare方法。

private static <T> void binarySort(T[] a, int lo, int hi, int start,
                                       Comparator<? super T> c) {
......
for ( ; start < hi; start++) {
            T pivot = a[start];
            ......
            while (left < right) {
                int mid = (left + right) >>> 1; //取中间索引
                if (c.compare(pivot, a[mid]) < 0) //2、使用外置算法:使用Comparator.compare方法比较当前值和中间值
                    right = mid;
                else
                    left = mid + 1;
            }
            ......
  }

测试:商品按照数量倒序且id正序排序

class Prodcut {
    ......
    public static void main(String[] args) {
			List<Product> products = new ArrayList<>();
			products.add(new Product(1l, "可乐", 50));
			products.add(new Product(2l, "雪碧", 70));
			products.add(new Product(3l, "酸奶", 70));
			products.add(new Product(4l, "牛奶", 80));
			Collections.sort(products, new Comparator<Product>() { //3、外置算法实现
				@Override
				public int compare(Product o1, Product o2) {
					if(o1 != null && o2 != null) {
						if (o1.count > o2.count) {
							return -1; // 数量倒序
						} else if (o1.count < o2.count) {
							return 1;
						} else if (o1.id > o2.id) {
							return 1; // id正序
						} else if (o1.id < o2.id) {
							return -1;
						} else {
							return 0;
						}
					}
					return 0;
				}
			});
			System.out.println(products);
		}
}

结果:

[[id:4, name:牛奶, count:80], [id:2, name:雪碧, count:70], [id:3, name:酸奶, count:70], [id:1, name:可乐, count:50]]

 

3、ADAPTER(适配器)— 类对象结构型模式

将一个类的接口转换成客户希望的另外一个接口。 而不能一起工作的那些类可以一起工作。

在没有字符流之前,字节流只能从文件里读出byte[]。

(不要使用DataInputStream.readUTF读取字符串,它只能按照阉割过的UTF-8解码)

如果要读出字符串需要:

文件 -> 字节流 -> byte[] -> 根据UTF-8等各种编码规则去解码 -> char[]

有了字符流之后,不需要自己解码。可以直接读出char[],那么JDK中将已有的字节流转换为字符流的InputStreamReader类就使用了适配器模式。

具体步骤:

1、抽象出需要适配的接口

2、构造方法传入被适配对象

3、使用成员变量保存被适配对象

4、使用被适配对象去实现适配接口

public class InputStreamReader extends Reader { //1、抽象出需要适配的接口:字符流Reader
    private final StreamDecoder sd; //流解码器

    public InputStreamReader(InputStream in) { //2、构造方法传入被适配对象:字节流InputStream
        super(in);
        try {
            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // 3、使用成员变量保存被适配对象:这里保存的是根据in创建解码器sd
        } catch (UnsupportedEncodingException e) {
            // The default encoding should always be available
            throw new Error(e);
        }
    }
    ......
    public int read(char cbuf[], int offset, int length) throws IOException {
        return sd.read(cbuf, offset, length); //4、使用被适配对象去实现适配接口:这里实际使用字节流创建的解码器,去读取字节并解码为字符
    }
    ......
}

BufferedReader.readLine方法,实际是先通过fill()方法读入到成员变量char cb[]中,再一行一行读出。

public class BufferedReader extends Reader {
    ......
    private void fill() throws IOException {
        ......
        int n;
        do {
            n = in.read(cb, dst, cb.length - dst); //实际使用InputStreamReader.read方法读取字符
        } while (n == 0);
        ......
    }
}

测试代码同"SINGLETON(单件)— 对象创建型模式"

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值