设计模式遵循六大原则
- 里氏替换原则
子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义:
子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
子类中可以增加自己特有的方法。
当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
- 依赖倒置原则
高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。依赖倒置原则的核心思想是面向接口编程
- 接口隔离原则
客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
- 迪米特法则
一个对象应该对其他对象保持最少的了解
- 开闭原则
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭
- 单一职责原则
即一个类只负责一项职责。
26种设计模式(分类概述)
创建型模式
单例模式,工厂模式(简单工厂模式,工厂方法模式),抽象工厂模式,建造者模式,原型模式
结构型模式
适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式
行为型模式
模板方法模式,命令模式,迭代器模式,观察者模式,中介者模式,备忘录模式,解释器模式,状态模式,策略模式,职责链模式,访问者模式
26种设计模式(详细介绍)
单例模式
饿汉式:简单,不存在同步问题。对象在使用前就创建,占内存。
//饿汉式单例模式
public class EhSingleton {
private EhSingleton(){};
private static EhSingleton eh=new EhSingleton();
public static EhSingleton getEhSingleton(){
return eh;
}
}
饱汉式:延迟加载,存在同步问题
//饱汉式单例模式,双重验证锁模式 DCL懒汉式
public class BhSingleton {
private BhSingleton(){};
private volatile static BhSingleton bhSingleton=null;
public static BhSingleton getBhSingleton(){
if(bhSingleton==null){
synchronized(BhSingleton.class){
if(bhSingleton==null){
bhSingleton=new BhSingleton();//不是原子操作,会发生指令重排序,使用volatile关键字
}
}
}
return bhSingleton;
}
}
使用静态内部类实现
public class singleton{
private singleton(){};
public static sibgleton getsingleton(){
return innerclass.SINGLETON;
};
public static class innerclass{
private static final singleton SINGLETON=new singleton();
单例模式是不安全的。因为有反射的存在。但是,反射不能破坏枚举的单例enum
工厂模式
简单工厂:静态工厂,不符合开闭原则。一个工厂生产多种产品。
public class CarFactory {
public Car getCar(String name){
if(name=="aodi"){
return new Aodi();
}else if(name=="mobai"){
return new Mobai();
}else
return null;
}
}
工厂方法
public class Client {
public static void main(String[] args) {
Car car1=new AodiFactory().getCar();
Car car2=new MoBaiFactory().getCar();
car1.getname();
car2.getname();
}
抽象工厂模式
类图结构示意
public class XiaomiFactory implements ProductFactory {
@Override
public IphoneProduct getPhone() {
return new xiaomiphone();
}
@Override
public DiannaoProduct getDiannao() {
return new xiaomidiannao();
}
}
public class MyTest {
public static void main(String[] args) {
XiaomiFactory xmf=new XiaomiFactory();
xiaomiphone xmp= (xiaomiphone) xmf.getPhone();
xiaomidiannao xmd= (xiaomidiannao) xmf.getDiannao();
System.out.println("=======小米产品=======");
xmp.playqq();
xmp.sendmsg();
xmd.wangye();
HuaweiFactory hwf=new HuaweiFactory();
huaweidiannao hwd= (huaweidiannao) hwf.getDiannao();
huaweiphone hwp= (huaweiphone) hwf.getPhone();
System.out.println("=======华为产品=======");
hwp.playqq();
hwp.sendmsg();
hwd.wangye();
}
}
建造者模式
public abstract class Builder {
abstract Builder builder1(String name1);
abstract Builder builder2(String name2);
abstract Builder builder3(String name3);
abstract Producter getProducter();
}
public class Worker extends Builder{
Producter pro
public Worker() {
pro=new Producter();
}
@Override
Builder builder1(String name1) {
pro.setName1(name1);
return this;
}
@Override
Builder builder2(String name2) {
pro.setName2(name2);
return this;
}
@Override
Builder builder3(String name3) {
pro.setName3(name3);
return this;
}
@Override
Producter getProducter() {
return pro;
}
}
public class Test {
public static void main(String[] args) {
Worker worker=new Worker();
//链式编程
Producter pro=worker.builder1("排骨").builder2("火锅").builder3("烤鸭")
.getProducter();
System.out.println(pro);
}
}
原型模式
根据一个原型,进行克隆
//1.实现Cloneable接口
//2.重写clone()方法
public class vedio implements Cloneable{
private String name;
private Date date;
public vedio(String name, Date date) {
this.name = name;
this.date = date;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj= super.clone();
//深度克隆
vedio v=(vedio)obj;
v.date=(Date) this.date.clone();
return obj;
}
@Override
public String toString() {
return "vedio{" +
"name='" + name + '\'' +
", date=" + date +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Date date=new Date();
vedio v1=new vedio("sql",date);
vedio v2=(vedio) v1.clone();
System.out.println("v1"+v1);
System.out.println("v2"+v2);
System.out.println("=========================");
date.setTime(233333333);
System.out.println("v1"+v1);
System.out.println("v2"+v2);
}
}
代理模式
静态代理:不符合开闭原则
目标对象和代理对象都要实现同一接口,代理对象包含目标对象
public class Proxyer implements Rent {
//目标对象
Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
@Override
public void rentHouse() {
//前置增强
kanfang();
rent.rentHouse();
//后置增强
hetong();
}
public void kanfang(){
System.out.println("代理带买家看房");
}
public void hetong(){
System.out.println("代理带买家签合同");
}
}
public class MyTest {
public static void main(String[] args) {
//目标对象
Host host=new Host();
//代理对象
Proxyer pro=new Proxyer();
pro.setRent(host);
pro.rentHouse();
}
}
动态代理
public class Proxyer implements InvocationHandler {
//目标对象
private Object target;
public void setTarget(Object target) {
this.target = target;
}
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
kanfang();
Object res=method.invoke(target,args);
hetong();
return res;
}
public void kanfang(){
System.out.println("代理带买家看房");
}
public void hetong(){
System.out.println("代理带买家签合同");
}
}
public class MyTest {
public static void main(String[] args) {
//目标对象
Host host=new Host();
Proxyer pro=new Proxyer();
pro.setTarget(host);
Rent rent=(Rent) pro.getProxy();
rent.rentHouse();
}
}
策略模式
鸭子项目:分离变化与不变;将变化的行为抽象为接口,和其实现类;不变的行为放在超类中,被继承。变化行为的实现类作为超类的实例变量,在构造函数中实例化。
策略模式 把易于变化的行为分别封装起来,让它们之间可以互相替换, 让这些行为的变化独立于拥有这些行为的客户。
用不同的算法做同一件事
JDK中的comparator接口;spring的初始化
命令模式
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
不同的命令做不同的事,常含有(关联)接收者。
命令模式是含有不同的命令(含有接收者的请求):做不同的事情;隐藏接收者执行细节。常见菜单事件,
而策略模式含有不同的算法,做相同的事情;
区别在于是否含有接收者。命令模式含有,策略模式不含有。命令模式中的命令可以单独运行。
队列请求
责任链模式
springmvc中的handlermapper;try catch异常处理;servlet filter过滤器
适配器模式
springmvc handleradapter