设计模式的六个原则
单一职责原则,英文:There should never be more than one reason for a class to change.翻译:一个类的改变不外乎一个原因(他的职责),不能有超过两个原因。我理解的意思就是一个类只干一种事情,不能多。如果用面向对象的思想去解释,举个例子,在学生考试系统里面,student类就是干学生相关的事情,比如学习、考试、做题;在teacher类中,就是教学、发卷子、改卷子。
里氏替换原则,Liskov Substitution Principle.它主要是讲Java里面的继承。继承有优点,比如说提高代码可复用性,每个子类都拥有父类的方法和属性,还有就是提高可扩展性和开放性。但是继承也有缺点,比如说继承是入侵式的,只要继承了,子类都将拥有父类的属性和方法;比如说父类的属性和方法修改了,必须考虑子类的修改,增加了耦合性;那这个里氏替换原则,其实就是如何让继承中的优点得到最大发挥,同时继承的缺点可以最大程度的减少。所以它阐述的主要是什么时候应该使用继承,什么时候不应该使用继承。明确的说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。想想也是可以理解的,你继承了父类,但又不使用父类,而是重写了父类,这样显然也不太科学。所以如果需要重写父类的方法,那么最好的方式就是改变继承的方式,定义一个更上层的父类;
依赖倒置原则,Dependence Inversion Principle.这个比较好理解,高层模块不应该依赖底层模块,抽象不依赖细节,细节应该依赖抽象。在具体实践上,模块间的依赖通过抽象产生,实现类应该都具有接口或抽象类,这是依赖倒置原则的基本要求,然后实现类之间不做依赖,细节不依赖细节。它的本质是通过抽象是各个模块实现彼此独立,互不影响,实现模块间的松耦合。
接口隔离原则,Interface Isolation Principle.即客户端不应该被强迫依赖它不需要的接口。其中的“客户端”,可以理解为接口的调用者或者使用者。接口的设计要尽量单一,不要让接口的实现类和调用者,依赖不需要的接口函数。需要什么就提供什么,不必多给。例如在系统中,我们肯定有订单服务,但是订单服务肯定有不同的订单,比如门票、酒店、机票等等,这样就可以设计不同的订单实现;同时对于管理平台的订单、外部第三方的订单还有其他BU的订单接口,也可以单独设计。
迪米特法则,Law of Demeter.它又称为最少知道原则。一个对象应该对其他对象尽可能少的了解,不要知道太多。如果真的很多,我们就需要考虑增加一个第三方的接口来帮忙我们把这个复杂的逻辑抽离出来。不如说用户关电脑,关电脑的过程计算机需要做很多事情,我们不需要在用户接口里显示关电脑的每个具体步骤,每个具体步骤应该放在电脑接口里面,或者关电脑的接口里面。
开闭原则。Software entities should be open for extension. but closed for modification. 一个软件实体应该对扩展开放,对修改关闭。这个原则说的是,在设计一个模块的时候,应当使这个可以在不修改的前提下被扩展。即应当可以在不必修改源代码的情况下改变这个模块的行为。以上五个原则,都是开闭原则的具体形态,它是总的指导方针。
UML之类图
类图,在UML类图中使用包含类名、属性(field) 和方法(method) 且带有分割线的矩形来表示一个类,比如下图表示一个Person类,它包含类名、id,name,male 3个属性、以及sayHello()和calcAddNuM两个方法。

表示方式
属性的完整表示方式是: 可见性 名称 :类型 [ = 缺省值]
方法的完整表示方式是: 可见性 名称(参数列表) [ : 返回类型]
可见性有三种标识
+:表示public
-:表示private
#:表示protected
类图是用来描述类和类之间的关系的,我整理了一张类图中各种关联关系以及图形形式,主要是一般关联、继承、实现

常用设计模式
单例模式,有多种形式,需要注意线程安全和效率
工厂模式,有多种形式
建造者模式,举个例子
package com.appleyk.test;
public class Aliyun {
private String appKey;
private String appSecret;
private String bucket;
private String endPoint;
public static class Builder {
private String appKey;
private String appSecret;
private String bucket;
private String endPoint;
public Builder appKey(String appKey) {
this.appKey = appKey;
return this;
}
public Builder appSecret(String appSecret) {
this.appSecret = appSecret;
return this;
}
public Builder bucket(String bucket) {
this.bucket = bucket;
return this;
}
public Builder endPoint(String endPoint) {
this.endPoint = endPoint;
return this;
}
public Aliyun build() {
return new Aliyun(this);
}
}
public static Builder builder() {
return new Aliyun.Builder();
}
private Aliyun(Builder builder) {
this.appKey = builder.appKey;
this.appSecret = builder.appSecret;
this.bucket = builder.bucket;
this.endPoint = builder.endPoint;
}
@Override
public String toString() {
return "Aliyun{" +
"appKey='" + appKey + '\'' +
", appSecret='" + appSecret + '\'' +
", bucket='" + bucket + '\'' +
", endPoint='" + endPoint + '\'' +
'}';
}
public static void main(String[] args) {
Aliyun aliyun = Aliyun.builder().appKey("123").appSecret("qwe").bucket("dd").endPoint("21qw").build();
System.out.println("build ok");
}
}
代理模式,有静态代理和动态代理。我们以访问Youtube为例子写个静态代理
public interface Web {
// 处理请求
void processRequest();
}
public class Youtube implements Web{
@Override
public void processRequest() {
System.out.println("你正在访问youtube");
}
}
public class VPN implements Web{
private Web web;
public VPN() {
}
public void setWeb(Web web) {
login();
charge();
this.web = web;
close();
}
@Override
public void processRequest() {
web.processRequest();
}
private void login() {
System.out.println("登录VPN");
}
private void charge() {
System.out.println("给VPN充值");
}
private void close() {
System.out.println("关闭VPN");
}
}
public class Client {
public static void main(String[] args) {
Web web = new Youtube();
VPN vpn = new VPN();
vpn.setWeb(web);
vpn.processRequest();
}
}
适配器模式,将一个类的接口转换成客户希望的另外一个接口 ProxyService Extends B implement A, 在A接口的实现方法中调用父类,实现转换。
桥梁模式
外观模式
命令模式
模板模式
责任链模式
策略模式
中介者模式
迭代器模式
观察者模式
备忘录模式
状态模式
解释器模式
访问者模式