创建模式包括工厂方法模式、建造者模式、抽象工厂方法、单例模式和原型模式,它们都能够提供对象的创建和管理指着。
其中的单例模式和原型模式非常容易理解,单例模式是要保持在内存中只有一个对象,原型模式是要求通过复制的方式产生一个对象。
工厂方法模式注重的是整体对象的创建方法,一个工厂专门生产一个对象,而建造者模式注重的是部件构件的过程,旨在通过一步一步地精确构造创建出一个复杂的对象。
如要制造一个超人,如果使用工厂方法模式,直接产生出来的就是一个力大无穷、能够飞翔、内裤外穿的超人;而如果使用建造者模式,则需要组装手、头、脚、躯干等部分,然后在把内裤外穿,构造一个超人。
意图不同
工厂模式是一个对象创建的粗线条应用,建造者模式则是通过细线条勾勒出一个复杂对象,关注的是产品组成部分的创建过程。
产品的复杂度不同
工厂方法模式创建的产品一般都是单一性质产品,如成年超人,都是一个模样。而建造者模式创建的则是一个复合产品,它由各个部件复合而成,部件不同 产品对象也就不同。
抽象工厂模式实现对产品家族的创建,一个从产品家族是这样的一系列产品:具有不同分类维度的产品组合。
抽象工厂模式则是不需要关心构建过程,只关心什么产品由什么工厂生产即可。主要在于应对“新系列”的需求变动。其缺点在于难以应对“新对象”的需求变动。
建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零件配件而产生一个新产品。
抽象工厂模式解决“系列对象”的需求变化,建造者模式解决“对象部分”的需求变化。
异常:程序执行出现的错误。
Java对于异常内容进行了区分和设置类型,我们把这种内容叫做异常类。异常类中异常是继承关系。
在Java类中,给我们提供了两种异常类:Exception、Error。
Exception:程序运行时异常,这种异常程序给我们提供了解决办法 try catch。
Error:JVM异常,程序无法处理,大多是程序员编写不符合Java规范。
java.lang.ArithmeticException 算数逻辑异常
java.lang.ArrayIndexOutOfBoundsException 下角标越界异常
java.lang.NullPointerException 访问成员为空
java.lang.ClassCastException类型转化异常
java.util.InputMismatchException 输入数据类型异常
在开发中,可以认为的设置异常。
自定义异常必须为类,而且继承Exception或RuntimeException。
class MyException extends Exception{
public MyException() {}
//Exception(s),当发生该异常时,打印s异常信息。
public MyException(String s) {
super(s);
}
}
受检查异常编译器在编译期间检查。对于这种异常,方法强制处理或者通过throws子句声明。其中一种情况是Exception的子类但不是RuntimeException的子类。
非受检查是RuntimeException的子类,在编译阶段不受编译器的检查。
try catch 解决异常
如果try里可能出现多种异常,catch该怎么办?
可以通过catch里的异常类别区分,发生什么异常就去执行哪个catch语句,类似于switch中的case语句
try{
//可能出现异常的语句
}catch(异常类 异常类对象){
//异常处理语句
}finally{
//一定会执行的语句!
}
throw用于抛出java.lang.Throwable类的一个实例化对象,意思是说可以同过关键字throw抛出一个Error或者一个Exception。
throws的作用是作为方法声明和签名的一部分,方法被抛出相应的异常以便调用者能处理。Java中,任何未处理的受检查异常强制在throws子句中声明。
#
|方法|作用|实例|
|:—|:—|:—|
|String(byte[])
|以byte数组初始化字符串,第二个参数可跟编码|s=String(bytes);
|
|int length()
|返回字符串长度|int i=str.length();
|
|char charAt(int index)
|返回字符串指定位置的单字符|char c=s.charAt(3);
|
|boolean contains(CharSequence)
|字符串是否包含序列|"123".contain("1");
|
|boolean equals(Object)
|将字符串与指定对象比较|s1.equal(s2);
|
|int compareTo(String)
|按字典顺序比较两个字符串,-1/0/1|s1.compareTo(s2);
|
|int indexOf(String)
|获取指定字符串在当前内容中首次出现的位置|s1.indexOf(s2);
|
|int lastindexOf(String)
|获取指定字符串在当前内容中最后出现的位置|s1.lastindexOf(s2);
|
|boolean startsWith(Stirng)
|测试此字符串是否以指定的前缀开始|s1.startsWith(s2);
|
|boolean endsWith(Stirng)
|测试此字符串是否以指定的后缀结束|s1.endsWith(s2);
|
|boolean regionMatches(int,String,int,int)
|测试此字符串是否以指定的后缀结束|s1.endsWith(s2);
|
|String substring(int,int)
|返回此字符串的一个子字串|"abcdefg".substring(2,4)="cd";
|
|String replaceAll(Sting,String)
|用新字符串替换匹配的字符串|s1.replace(" ","");
|
|String trim()
|返回字符串的副本,忽略前导空白和尾部空白。|" 12 3 4 ".trim() == "12 3 4";
|
|String concat(String)
|将指定字符串连接到此字符串的结尾。| "12".concat("23");
|
|String[] split(regex)
|根据给定正则表达式的匹配拆分此字符串。注意:每遇到一个regex前后分割|"12 3 4 ".split(" ");[, 1, 2, 3, 4]
|
相关用法:
//int型转字符串
String s1 = 10 + "";
//字符串转int
int i = Integer.parseInt(s1);
//注意 t x = T.parseT(String) t是基本类型,T是对应引用类型,将字符串转为t类型
//字符串转字符数组
String string = "abcdefg";
char[] array = string.toCharArray();
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+" ");
}
//字符串转字节数组
byte[] bs = string.getBytes();
for (int i = 0; i < bs.length; i++) {
System.out.println(bs[i]+" ");
}
输出:97 98 99 100 101 102 103
//字节数组初始化字符串
String str = new String(bs);
//Arrays下的toString方法
String[] strs = "12 3 4 ".split(" ");
System.out.println(Arrays.toString(strs));
输出:[, 1, 2, 3, 4]
//获取1970.1.1 0点到当前时间的毫秒值 两种方法
long l1 = System.currentTimeMillis();
long l2 = new Date().getTime();
//获取当前日期时间
Date date = new Date();
System.out.println(date);
输出结果格式:Tue Mar 19 23:30:14 CST 2019
SimpleDateFormat:
//格式化1
SimpleDateFormat sdf = new SimpleDateFormat();
String s1 = sdf.format(new Date());
System.out.println(s1);
输出:19-3-19 下午11:41
//格式化2
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日");
String s2 = sdf1.format(new Date());
System.out.println(s2);
输出:2019年03月19日
//解析
SimpleDateFormat sdf3 = new SimpleDateFormat();
Date d1 = sdf3.parse("19-3-18 下午7:37");
System.out.println(d1);
输出:Mon Mar 18 19:37:00 CST 2019
三天打渔两天晒网基础
@Test
public void fun(){
Date date = new Date();
long l = date.getTime();
int d = (int)(l/100/3600/24)+1;
if(d%5==0 && d%5==4){
System.out.println("晒网");
}else{
System.out.println("打渔");
}
}
三天打渔两天晒网扩展
@Test
public void fun(){
String date1 = "1990-01-01";
String date2 = "2022-03-04";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy--MM--dd");
Date d1 = sdf(date1);
Date d2 = sdf(date2);
long ms = d2.getTime() - d1.getTime();
int d = (int)(ms/1000/3600/24)+1;
if(d%5==0 && d%5==4){
System.out.println("晒网");
}else{
System.out.println("打渔");
}
}
#
按流的方向分为:输入流 和 输出流
按数据结构分为:字节流 和 字符流
按角色分为:节点流 和 缓冲流(处理流
InputStream:字节输入流
OutputStream:字节输出流
Reader:字符输入流
Writer:字符输出流
|抽象类|基本实现类(节点流)|缓冲流| |:—|:—|:—| |InputStream|FileInputStream|BufferedInputStream| |OutputStream|FileOutputStream|BufferedOutputStream (flush())| |Reader|FileReader|BufferedReader (readLine())| |Writer|FileWriter|BufferedWriter (flush())|
public class TestFile {
public static void main(String[] args) {
// 声明文件
File f1 = new File("Test1.txt");
// 创建操作文件对象
FileInputStream fis = null;
try {
fis = new FileInputStream(f1);
byte[] bs = new byte[6];
while(fis.read(bs)!=-1 ) {
String s = new String(bs);
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fis !=null) {
try {
fis.close();
} catch (IOException e{
e.printStackTrace();
}
}
}
}
}
##FileOutputStream
public class TestFile2 {
public static void main(String[] args){
// 输出流的时候如果底层没有文件,系统会给你创建一个文件
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File("Test2.txt"));
fos.write(new String("你在干嘛呢").getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fos !=null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
##利用缓冲流实现文件内容的拷贝
@Test
public void fun9() {
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(new File("Test1.txt")));
bw = new BufferedWriter(new FileWriter(new File("Test2.txt")));
String str;
while((str=br.readLine())!=null) {
bw.write(str);
}
bw.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(bw!=null)
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
if(br!=null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
#
Singleton模式解决的是实体对象个数的问题,除了Singleton之外,其他创建型模式解决的都是new所带来的耦合关系。
Factory Method,Abstract Factory,Builder都需要一个额外的工厂类来负责实例化“易变对象”,而Prototype则是通过原型(一个特殊的工厂类)来克隆“易变对象”。
如果遇到“易变类”,起初的设计通常从Factory Method开始,当遇到跟多的复杂变化时,再考虑重构为其他三种工厂模式(Abstract Factory,Builder,Prototype)。
Adapter模式注重转换接口,将不吻合的接口适配对接。
Bridge模式注重分离接口与其实现,支持多维度变化。
Composite模式注重统一接口,将“一对多”的关系转化为“一对一”的关系。
Decorator模式注重稳定接口,在此前提下为对象扩展功能。
Facade模式注重简化接口,简化组件系统与外部客户程序的依赖关系。
Flyweight模式注重保留接口,在内部使用共享技术对对象存储进行优化。
Proxy模式注重假借接口,增加简介层来实现灵活控制。
Template Method模式封装算法结构,支持算法子步骤变化。
Strategy模式注重封装算法,支持算法的变化。
State模式注重封装与状态显像管的行为,支持状态的变化。
Memento模式注重封装对象状态变化,支持状态保存/恢复。
Mediator模式注重封装对象间的交互,支持对象交互的变化。
Chain Of Responsibility模式注重封装对象责任,支持责任的变化。
Command模式注重将请求封装为对象,支持请求的变化。
Iterator模式注重封装集合对象内部结构,支持集合的变化。
Interpreter模式注重封装特定领域变化,支持领域问题的频繁变化。
Observer模式注重封装对象通知,支持通信对象的变化。
Visitor模式注重封装对象操作变化,支持在运行时为类层次结构动态添加新的操作。
设计模式建立在对系统变化点的基础上进行,哪里有变化点,哪里应用设计模式。
设计模式应该以演化的方式来获得,系统的变化点往往是经过不断演化才能准确定位。
不能为了模式而模式,设计模式是一种软件设计的软力量,而非规范标准。不应夸大设计模式的作用。
类层次结构中可能经常由于引入新的操作,从而将类型变得脆弱
在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的更改,将会给子类带来很繁重的变更负担,甚至破坏原有设计。
如何在不更改类层次结构的前提下,在运行时根据需要透明地为类层次结构上的各个类动态添加新的操作,从而避免上述问题?
表示一个作用于某对象结构中的各元素的操作。它可以在不改变各元素的类的前提下定义作用于这些元素的新的操作。
Visitor:抽象访问者 抽象类或接口,声明访问者可以访问哪些元素。
ConcreteVisitor:具体访问者 它影响访问者访问到一个类后该怎么干,要做什么。
Element:抽象元素 抽象类或接口,声明接受哪一类访问者访问。
ConcreteElement:具体元素 实现accept方法,通常是visitor.visit(this)。
Visitor模式通过所谓双重分发来实现在不更改Element类层次结构的前提下,在运行时透明地为类层次结构上的各个类动态添加新的操作。
所谓双重分发即Visitor模式中间包括了两个多态分发(注意其中的多态机制):第一个为accept方法的多态辨析;第二个为visit方法的多态辨析。
抽象元素:
public abstract class Element{
//定义业务逻辑
public abstract void doSomething();
//允许谁来访问
public abstract void accept(IVisitor visitor);
}
具体元素:
public class ConcreteElement1 extends Element{
//完善业务逻辑
public void doSomething(){
//业务处理
}
public void accept(IVisitor visitor)[
visitor.visit(this);
}
}
public class ConcreteElement2 extends Element{
//完善业务逻辑
public void doSomething(){
//业务处理
}
public void accept(IVisitor visitor)[
visitor.visit(this);
}
}
抽象访问者:
public interface IVisitor{
//可以访问哪些对象
public void visit(ConcreteElement el1);
public void visit(CpncreteElement el2);
}
具体访问者:
public class Visitor implements IVisitor{
//访问el1元素
public void visit(ConcreteElement1 el1){
el1.doSomething();
}
//访问el2元素
public void visit(ConcreteElement2 el2){
el2.doSomething();
}
}
结构对象:
public class ObjectStruture{
//对象生成器,这里通过一个工厂方法模式模拟
public static Element createElement(){
Random rand = new Random();
if(rand.nextInt(100)>50){
return new ConcreteElement1();
}else{
return new ConcreteElement2()
}
}
}
场景类:
public class Client{
public static void main(String[] args){
for(int i=0;i<10;i++){
//获得元素对象
Element el = ObjectStruture.createElement();//接受访问者访问
el.accept(new Visitor());
}
}
}