创建型模式-工厂方法

维基百科 工厂方法 工厂方法模式(英语:Factory method pattern)是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题。工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。” 创建一个对象常常需要复杂的过程,所以不适合包含在一个复合对象中。创建对象可能会导致大量的重复代码,可能会需要复合对象访问不到的信息,也可能提供不了足够级别的抽象,还可能并不是复合对象概念的一部分。工厂方法模式通过定义一个单独的创建对象的方法来解决这些问题。由子类实现这个方法来创建具体类型的对象。 对象创建中的有些过程包括决定创建哪个对象、管理对象的生命周期,以及管理特定对象的创建和销毁的概念。 工厂 在面向对象程序设计中,工厂通常是一个用来创建其他对象的对象。工厂是构造方法的抽象,用来实现不同的分配方案。 工厂对象通常包含一个或多个方法,用来创建这个工厂所能创建的各种类型的对象。这些方法可能接收参数,用来指定对象创建的方式,最后返回创建的对象。 有时,特定类型对象的控制过程比简单地创建一个对象更复杂。在这种情况下,工厂对象就派上用场了。工厂对象可能会动态地创建产品类的对象,或者从对象池中返回一个对象,或者对所创建的对象进行复杂的配置,或者应用其他的操作。 这些类型的对象很有用。几个不同的设计模式都应用了工厂的概念,并可以使用在很多语言中。例如,在《设计模式》一书中,像工厂方法模式、抽象工厂模式、生成器模式,甚至是单例模式都应用了工厂的概念。 代码举例 例如,有一个Button类表示按钮,另有它的两个子类WinButton和MacButton分别代表Windows和Mac风格的按钮,那么这几个类和用于创建它们的工厂类在Java中可以如下实现 //Button class Button{/* ...*/} class WinButton extends Button{/* ...*/} class MacButton extends Button{/* ...*/} //他们的工厂类 interface ButtonFactory{ abstract Button createButton(); } class WinButtonFactory implements ButtonFactory{ Button createButton(){ return new WinButton(); } } class MacButtonFactory implements ButtonFactory{ Button createButton(){ return new MacButton(); } } 简单工厂 普通的工厂方法模式通常伴随着对象的具体类型与工厂具体类型的一一对应,客户端代码根据需要选择合适的具体类型工厂使用。然而,这种选择可能包含复杂的逻辑。这时,可以创建一个单一的工厂类,用以包含这种选择逻辑,根据参数的不同选择实现不同的具体对象。这个工厂类不需要由每个具体产品实现一个自己的具体的工厂类,所以可以将工厂方法设置为静态方法。 而且,工厂方法封装了对象的创建过程。如果创建过程非常复杂(比如依赖于配置文件或用户输入),工厂方法就非常有用了。 比如,一个程序要读取图像文件。程序支持多种图像格式,每种格式都有一个对应的ImageReader类用来读取图像。程序每次读取图像时,需要基于文件信息创建合适类型的ImageReader。这个选择逻辑可以包装在一个简单工厂中: public class ImageReaderFactory { public static ImageReader imageReaderFactoryMethod(InputStream is) { ImageReader product = null; int imageType = determineImageType(is); switch (imageType) { case ImageReaderFactory.GIF: product = new GifReader(is); case ImageReaderFactory.JPEG: product = new JpegReader(is); //... } return product; } } 适用性 下列情况可以考虑使用工厂方法模式: ...

August 19, 2019 · 2 min · zhangxiaofeng05

java接口回调

回调一般用于层间协作,上层将本层函数安装在下层,这个函数就是回调,而下层在一定条件下触发回调。例如作为一个驱动,是一个底层,他在收到一个数据时,除了完成本层的处理工作外,还将进行回调,将这个数据交给上层应用层来做进一步处理,这在分层的数据通信中很普遍。 例如老板A对员工B说,我现在交给你一个任务,并且我把我的电话号码给你,你一旦完成任务就给我打电话。 1.创建一个回调接口 /** * 一个回调接口 */ public interface CallBack { public void doEvent(); } 2.创建回调接口的实现类,此例中,员工干完活后还要干什么事情是老板说了算的。 /** * 回调接口的实现类 */ public class Boss implements CallBack{ @Override public void doEvent() { System.out.println("打电话给老板,告知已完成工作了"); } } 3.创建控制类,也就是本例中的员工对象,他要持有老板的地址(即回调接口) /** * 控制类,也就是本例中的员工对象,他要持有老板的地址(即回调接口) */ public class Employee { CallBack callBack; public Employee(CallBack callBack){ this.callBack=callBack; } public void doWork(){ System.out.println("玩命干活中"); callBack.doEvent(); } } 4.测试类 /** * 测试类 */ public class TestMain { public static void main(String[] args) { Employee employee = new Employee(new Boss()); employee.doWork(); } } 运行结果: ...

August 17, 2019 · 1 min · zhangxiaofeng05

mysql高级排序

表和数据 CREATE TABLE `sqltest` ( `id` int(11) NOT NULL, `name` varchar(45) NOT NULL, `age` int(11) NOT NULL, `score` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `id_UNIQUE` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `sqltest` VALUES (1,'土豆',18,100),(2,'地瓜',18,100),(3,'李斯',20,60),(4,'韩非',20,60),(5,'荀子',50,90),(6,'君莫笑',22,80),(7,'寒烟柔',21,80),(8,'包子',26,30),(9,'剑圣',30,0); 排名(row_number) 按分数排序,拿到名次(成绩相同排名不并列) SQL: use sqltest; select st.*,(@rownum:=@rownum+1) as rownum from sqltest st,(select @rownum:=0) potato order by score; 结果: 解释:设置一个伪列@rownum,从1开始计数,依次加1;(select @rownum:=0) potato ,一定要起别名 注意:这是从小到大排;如果需要从大到小的话,order by score desc。 排名(Rank) 按分数排序,拿到名次(成绩相同排名并列,有跳数,比如2个100,1个99,排名就是1,1,3) SQL: use sqltest; select st.*,@rownum:=@rownum+1 as rownum, @curnum:=(case when @prescore=st.score then @curnum else @rownum end) as ScoreRank, @prescore:=st.score as prescore from sqltest st,(select @rownum:=0,@curnum:=0,@prescore:=null) potato order by st.score desc; 结果: ...

August 17, 2019 · 1 min · zhangxiaofeng05

TCP、UDP简单聊天

TCP 客户端套接字:Socket 服务端套接字:ServerSocket TCP(传输控制协议)一种基于连接的通信协议。可靠传输 Server package com.tcp; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /** * 服务器端 */ public class Server { public static void main(String[] args) { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(12345); System.out.println("服务启动:"+serverSocket.getInetAddress().getHostAddress()+":"+serverSocket.getLocalPort()); Socket accept = serverSocket.accept(); System.out.println("客户端:"+accept.getInetAddress().getHostAddress()+":"+accept.getLocalPort()); BufferedReader sis = new BufferedReader(new InputStreamReader(System.in)); BufferedReader is = new BufferedReader(new InputStreamReader(accept.getInputStream())); PrintWriter os = new PrintWriter(new OutputStreamWriter(accept.getOutputStream())); while (true){ String line; if ((line=is.readLine())!=null){ System.out.println("收到客户端:"+line); if (line.equals("bye")){ break; }else { os.println(sis.readLine()); os.flush(); } } } is.close(); os.close(); accept.close(); } catch (IOException e) { e.printStackTrace(); }finally { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } Client package com.tcp; import java.io.*; import java.net.Socket; /** * 客户端 */ public class Client { public static void main(String[] args) { try { Socket socket = new Socket("127.0.0.1",12345); BufferedReader sis = new BufferedReader(new InputStreamReader(System.in)); BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter os = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); String line; while (true){ if ((line=sis.readLine())!=null){ if ("bye".equals(line)){ System.exit(0); } os.println(line); os.flush(); } String readLine = is.readLine(); System.out.println("收到服务端:"+readLine); } } catch (IOException e) { e.printStackTrace(); } } } UDP UDP采用Datagram(数据报)传输,数据包是一种尽力而为的传送数据的方式,它只是 把数据的目的地记录在数据包中,然后就直接放在网络上,系统不保证数据是否能安全到达,或者什么时候可以送到,它并不保证传送质量。 ...

July 30, 2019 · 2 min · zhangxiaofeng05

反射

java.lang.Class 创建一个类,通过编译(javac.exe),生成对应的.class文件。之后使用java.exe加载(JVM的类加载器完成), 此.class文件加载到内存以后,就是一个运行时类,存在缓冲区。那么这个运行时类本身就是一个Class的实例! 一个运行时类只加载一次。 举例 import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class RelfectTest{ public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException { Class<Person> personClass = Person.class; //通过反射创建对象 Person person = personClass.newInstance(); System.out.println(person); //通过反射赋值-------public属性 Field name = personClass.getField("name"); name.set(person,"土豆"); System.out.println(person); //通过反射赋值------private或者默认(不写)属性 Field age = personClass.getDeclaredField("age"); age.setAccessible(true); age.set(person,18); System.out.println(person); //通过反射调用指定方法--没有参数 Method show = personClass.getMethod("show"); show.invoke(person); //通过反射调用指定方法--有参数 Method say = personClass.getMethod("say", String.class); say.invoke(person,"welcome"); } } class Person{ public String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return name+"----"+age; } public void show(){ System.out.println("Person类的show..."); } public void say(String word){ System.out.println(name+" "+word); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } 拓展 Person类 ...

July 28, 2019 · 5 min · zhangxiaofeng05

==和equals和hashCode

==和equals == 基本类型:比较的是值是否相同; 引用类型:比较的是内存地址是否相同(是否是同一对象); equals Object类中的equals方法 public boolean equals(Object obj) { return (this == obj); } String类重写了equals方法 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; } 举例: ...

July 28, 2019 · 4 min · zhangxiaofeng05

java IO流

从控制台输入输出 import java.util.Scanner; public class IoTest { public static void main(String args[]){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); System.out.println(n); String s = sc.next(); System.out.println(s); String line = sc.nextLine(); System.out.println(line);//从控制台输出 } } 字节流 FileOutputStream import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStream; public class IoTest { public static void main(String args[]){ File file = new File("aa.txt"); try { //FileOutputStream(File,boolean) 是否把内容追加 OutputStream out = new FileOutputStream(file); String str = "Hello World"; byte[] b=str.getBytes(); out.write(b); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } } FileInputStream import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; public class IoTest { public static void main(String args[]){ try { File file = new File("E:"+File.separator+"tt.txt"); InputStream is = new FileInputStream(file); // byte[] bytes = new byte[1024]; //也可以这样 byte[] bytes = new byte[(int) file.length()]; is.read(bytes); System.out.println(new String(bytes)); //关闭流 is.close(); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } } BufferedOutputStream import java.io.*; public class IoTest { public static void main(String args[]){ File file = new File("aa.txt"); try { OutputStream out = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(out); byte[] bytes = "土豆,土豆,呼叫土豆".getBytes(); bos.write(bytes); //刷新缓存 bos.flush(); bos.close(); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } } BufferedInputStream import java.io.*; public class IoTest { public static void main(String args[]){ try { File file = new File("E:"+File.separator+"tt.txt"); InputStream is = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(is); byte[] bytes = new byte[(int) file.length()]; bis.read(bytes); System.out.println(new String(bytes)); bis.close(); is.close(); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } } 字符流 FileWriter import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; public class IoTest { public static void main(String args[]){ try { File file = new File("aa.txt"); Writer writer = new FileWriter(file); writer.write("土豆。。。\n"); writer.write("地瓜,对不起"); writer.close(); } catch (IOException e) { e.printStackTrace(); } } } FileReader import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.Reader; public class IoTest { public static void main(String args[]){ try { File file = new File("aa.txt"); Reader reader = new FileReader(file); char[] chars = new char[1024]; reader.read(chars); System.out.println(new String(chars)); reader.close(); } catch (IOException e) { e.printStackTrace(); } } } 转换流(字节流转字符流) OutputStreamWriter import java.io.*; public class IoTest { public static void main(String args[]){ File file = new File("aa.txt"); try { OutputStream out = new FileOutputStream(file); OutputStreamWriter osw = new OutputStreamWriter(out); osw.write("这是字节流转成了字符流"); String encoding = osw.getEncoding(); System.out.println("文件的编码:"+encoding); //文件的编码:UTF8 osw.close(); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } } InputStreamReader import java.io.*; public class IoTest { public static void main(String args[]){ try { File file = new File("aa.txt"); InputStream is = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(is,"utf-8");//指定编码 char[] chars = new char[1024]; isr.read(chars); System.out.println(chars); System.out.println("编码:"+isr.getEncoding()); isr.close(); isr.close(); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } } 字符缓冲流(高效流) BufferedWriter import java.io.*; public class IoTest { public static void main(String args[]){ File file = new File("aa.txt"); try { OutputStream out = new FileOutputStream(file); OutputStreamWriter osw = new OutputStreamWriter(out); BufferedWriter bw = new BufferedWriter(osw); bw.write("hello 这是字符缓冲流"); bw.newLine(); bw.write("下一行"); bw.close(); osw.close(); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } } BufferedReader import java.io.*; public class IoTest { public static void main(String args[]){ try { File file = new File("aa.txt"); InputStream is = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(is,"utf-8"); BufferedReader br = new BufferedReader(isr); String str; while ((str=br.readLine())!=null){ System.out.println(str); } br.close(); isr.close(); is.close(); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } } 字节流与字符流的区别 字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的 ...

July 25, 2019 · 3 min · zhangxiaofeng05

java异常

异常类型 检查性异常 最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。 运行时异常 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略(Throw)。 错误 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。 异常类Exception 构造方法 public Exception() 构建一个新的异常,以 null作为其详细信息。 public Exception(String message) 使用指定的详细消息构造新的异常。 public Exception(String message, Throwable cause) 构造一个新的异常与指定的详细信息和原因。 public Exception(Throwable cause) 构造一个新的异常与指定原因。 protected Exception(String message, Throwable cause,boolean enableSuppression,boolean writableStackTrace) 构造一个新的异常,其中包含指定的详细消息,启用或禁用抑制功能,启用或禁用可写栈跟踪。 常用方法 public String getMessage() 返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。 public Throwable getCause() 返回一个Throwable 对象代表异常原因。 public String toString() 使用getMessage()的结果返回类的串级名字。 public void printStackTrace() 打印toString()结果和栈层次到System.err,即错误输出流。 public StackTraceElement [] getStackTrace() 返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。 public Throwable fillInStackTrace() 用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。 处理异常 try-catch public class MyException extends Exception{ public static void main(String[] args) { try { int i=1/0; }catch (ArithmeticException e){ e.printStackTrace(); } catch (Exception e){ e.printStackTrace(); System.out.println("这是总异常"); }finally { System.out.println("无论有没有异常,都会执行。比如用于关闭数据库的连接"); } } } throws public class MyException extends Exception{ public static void main(String[] args) { MyException myException = new MyException(); try { myException.show(); } catch (Exception e) { e.printStackTrace(); } } public void show() throws Exception{//抛出去,谁调用谁处理 int i=1/0; } } 注意事项 throws在方法名后边 catch 不能独立于 try 存在。 在 try/catch 后面添加 finally 块并非强制性要求的。 try 代码后不能既没 catch 块也没 finally 块。 try, catch, finally 块之间不能添加任何代码。 ...

July 25, 2019 · 1 min · zhangxiaofeng05

Java中Date、SimpleDateFormat、Calendar

jdk1.8 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * Java 语言的Date(日期),Calendar(日历),DateFormat(日期格式)组成了Java标准的一个基本但是非常重要的部分。 */ public class StringTest { public static void main(String[] args) throws ParseException { Date currentTime = new Date(); System.out.println(currentTime); //设置时间格式 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println(simpleDateFormat.format(currentTime)); SimpleDateFormat year = new SimpleDateFormat("yyyy");//获取年----其它类似 System.out.println(year.format(currentTime)); Date date = simpleDateFormat.parse("2019-1-23 12:00:00");//把字符串转换成日期 System.out.println(simpleDateFormat.format(date)); //计算时间差currentTime-date相差多少天 Long days = (currentTime.getTime()-date.getTime())/(1000*60*60*24);//参数--毫秒 System.out.println(days); System.out.println("---------------------------利用Calendar获取时间值比较方便"); // Calendar转化为Date Calendar cal=Calendar.getInstance(); Date date1=cal.getTime(); // Date转化为Calendar Calendar cal2=Calendar.getInstance(); cal2.setTime(date); //计算某个日期是那一年的第几天 int d = cal2.get(Calendar.DAY_OF_YEAR); System.out.println(d); //一年的第几周等。。 } }

July 24, 2019 · 1 min · zhangxiaofeng05

String、StringBuffer、StringBuilder的区别

长度是否可变 String 是被 final 修饰的,他的长度是不可变的,就算调用 String 的concat 方法,那也是把字符串拼接起来并重新创建一个对象,把拼接后的 String 的值赋给新创建的对象 StringBuffer 和 StringBuilder修改本身 执行效率 三者在执行速度方面的比较:StringBuilder > StringBuffer > String 应用场景 如果要操作少量的数据用 = String 单线程操作字符串缓冲区 下操作大量数据 = StringBuilder 多线程操作字符串缓冲区 下操作大量数据 = StringBuffer 线程安全 StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问),StringBuffer是线程安全的。只是StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是线程不安全的。 参考 https://www.cnblogs.com/AmyZheng/p/9415064.html

July 24, 2019 · 1 min · zhangxiaofeng05