设计模式初识
设计模式
1、设计模式七大原则
-
开闭原则
对扩展开放,对修改关闭
-
单一职责原则
一个类只干一件事,实现类要单一
-
里氏替换原则
不要破坏继承体系,子类重写方法功能发生改变,不应该影响父类方法的含义
-
依赖倒转原则
高层不应该依赖低层,要面向接口编程。
-
接口隔离原则
一个接口只干一件事,接口要精简单一
-
迪米特法则
不该知道的不要知道,一个类应该保持对其它对象最少的了解,降低耦合度
-
合成复用原则
尽量使用组合或者聚合关系实现代码复用,少使用继承
2、设计模式分类
-
创建型模式
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。
-
结构型模式
这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。
-
行为型模式
这些设计模式特别关注对象之间的通信。
2、设计模式全部
不常用
-
创建型模式
工厂模式、抽象工厂模式、单例模式、建造者模式
原型模式
-
结构型模式
适配器模式、装饰器模式、代理模式、桥接模式
外观模式、组合模式、享元模式
-
行为型模式
策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、状态模式
命令模式、备忘录模式、访问者模式、中介模式、解释器模式
总览
分类 | 设计模式 | 简述 | 一句话归纳 | 目的 | 生活案例 |
---|---|---|---|---|---|
创建型设计模式 (简单来说就是用来创建对象的) |
工厂模式(Factory Pattern) | 不同条件下创建不同实例 | 产品标准化,生产更高效 | 封装创建细节 | 实体工厂 |
单例模式(Singleton Pattern) | 保证一个类仅有一个实例,并且提供一个全局访问点 | 世上只有一个我 | 保证独一无二 | CEO | |
原型模式(Prototype Pattern) | 通过拷贝原型创建新的对象 | 拔一根猴毛,吹出千万个 | 高效创建对象 | 克隆 | |
建造者模式(Builder Pattern) | 用来创建复杂的复合对象 | 高配中配和低配,想选哪配就哪配 | 开放个性配置步骤 | 选配 | |
结构型设计模式 (关注类和对象的组合) |
代理模式(Proxy Pattern) | 为其他对象提供一种代理以控制对这个对象的访问 | 没有资源没时间,得找别人来帮忙 | 增强职责 | 媒婆 |
外观模式(Facade Pattern) | 对外提供一个统一的接口用来访问子系统 | 打开一扇门,通向全世界 | 统一访问入口 | 前台 | |
装饰器模式(Decorator Pattern) | 为对象添加新功能 | 他大舅他二舅都是他舅 | 灵活扩展、同宗同源 | 煎饼 | |
享元模式(Flyweight Pattern) | 使用对象池来减少重复对象的创建 | 优化资源配置,减少重复浪费 | 共享资源池 | 全国社保联网 | |
组合模式(Composite Pattern) | 将整体与局部(树形结构)进行递归组合,让客户端能够以一种的方式对其进行处理 | 人在一起叫团伙,心在一起叫团队 | 统一整体和个体 | 组织架构树 | |
适配器模式(Adapter Pattern) | 将原来不兼容的两个类融合在一起 | 万能充电器 | 兼容转换 | 电源适配 | |
桥接模式(Bridge Pattern) | 将两个能够独立变化的部分分离开来 | 约定优于配置 | 不允许用继承 | 桥 | |
行为型设计模式 (关注对象之间的通信) |
模板模式(Template Pattern) | 定义一套流程模板,根据需要实现模板中的操作 | 流程全部标准化,需要微调请覆盖 | 逻辑复用 | 把大象装进冰箱 |
策略模式(Strategy Pattern) | 封装不同的算法,算法之间能互相替换 | 条条大道通罗马,具体哪条你来定 | 把选择权交给用户 | 选择支付方式 | |
责任链模式(Chain of Responsibility Pattern) | 拦截的类都实现统一接口,每个接收者都包含对下一个接收者的引用。将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。 | 各人自扫门前雪,莫管他们瓦上霜 | 解耦处理逻辑 | 踢皮球 | |
迭代器模式(Iterator Pattern) | 提供一种方法顺序访问一个聚合对象中的各个元素 | 流水线上坐一天,每个包裹扫一遍 | 统一对集合的访问方式 | 逐个检票进站 | |
命令模式(Command Pattern) | 将请求封装成命令,并记录下来,能够撤销与重做 | 运筹帷幄之中,决胜千里之外 | 解耦请求和处理 | 遥控器 | |
状态模式(State Pattern) | 根据不同的状态做出不同的行为 | 状态驱动行为,行为决定状态 | 绑定状态和行为 | 订单状态跟踪 | |
备忘录模式(Memento Pattern) | 保存对象的状态,在需要时进行恢复 | 失足不成千古恨,想重来时就重来 | 备份、后悔机制 | 草稿箱 | |
中介者模式(Mediator Pattern) | 将对象之间的通信关联关系封装到一个中介类中单独处理,从而使其耦合松散 | 联系方式我给你,怎么搞定我不管 | 统一管理网状资源 | 朋友圈 | |
解释器模式(Interpreter Pattern) | 给定一个语言,定义它的语法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子 | 我想说”方言“,一切解释权都归我 | 实现特定语法解析 | 摩斯密码 | |
观察者模式(Observer Pattern) | 状态发生改变时通知观察者,一对多的关系 | 到点就通知我 | 解耦观察者与被观察者 | 闹钟 | |
访问者模式(Visitor Pattern) | 稳定数据结构,定义新的操作行为 | 横看成岭侧成峰,远近高低各不同 | 解耦数据结构和数据操作 | KPI考核 | |
委派模式(Delegate Pattern) | 允许对象组合实现与继承相同的代码重用,负责任务的调用和分配 | 这个需求很简单,怎么实现我不管 | 只对结果负责 | 授权委托书 |
一、六大原则
宗旨:面向接口开发,不要面向实现开发。
记忆口诀:访问加限制,函数要节俭,依赖不允许,动态加接口,父类要抽象,扩展不更改。
1、开闭原则
对扩展开放,对修改关闭
2、里氏替换原则
里氏替换原则主要阐述了有关继承的一些原则
子类可以扩展父类的功能,但不能改变父类原有的功能
3、依赖倒转原则
高层不应该依赖底层,面向接口
即:接口不能依赖实现
4、单一职责原则
一个类只做一种事,实现要单一
即:实现类不能实现不同功能的接口
5、接口隔离原则
一个接口只做一件事,接口要简单单一
即:将同类的方法封装在同一个接口中
6、迪米特法则
一个类应保持对其他对象更少的了解,降低耦合度
如:明星和经纪人的关系,明星只负责去干自己的事,不用去了解其他的
二、23种设计模式
-
创建型模式
工厂方法模式、单例模式、原型模式、抽象工厂模式、建造者模式
-
结构型模式
适配器模式、代理模式、桥接模式、装饰模式、外观模式、享元模式、组合模式
-
行为型模式
模板方法模式、解释器模式、策略模式、命令模式、职责链模式、状态模式、观察者模式、中介者模式、迭代器模式、访问者模式、备忘录模式
1、单例模式
只存在一个对象实例
运用场景:只需要单一实例的对象
//双判
public class SingleToneDemo {
public static void main(String[] args) {
System.out.println(SingleTone.getInstance());
System.out.println(SingleTone.getInstance());
}
}
class SingleTone {
private static volatile SingleTone instance;
public SingleTone() {
}
public static SingleTone getInstance() {
if (instance == null) {
synchronized (SingleTone.class) {
}
}
return instance;
}
}
2、工厂方法模式
结构:
抽象工厂(创建单个产品)、具体工厂、抽象产品,具体产品
public class FactoryDemo {
public static void main(String[] args) {
Factory factory ;
Product product ;
factory = new FactoryImpl();
product = factory.create();
product.show();
}
}
interface Factory {
Product create();
}
class FactoryImpl implements Factory {
@Override
public Product create() {
System.out.println("创建成功");
return new ProductImpl();
}
}
interface Product {
void show();
}
class ProductImpl implements Product {
@Override
public void show() {
System.out.println("产品实体类展示");
}
}
3、抽象工厂模式
结构:
抽象工厂(创建多个产品)、具体工厂、抽象产品,具体产品
public class AbstractFactoryDemo {
public static void main(String[] args) {
AbstractFactory abstractFactory;
Product1 product1;
Product2 product2;
abstractFactory = new AbstractFactoryImpl();
product1 = abstractFactory.create1();
product2 = abstractFactory.create2();
product1.show();
product2.show();
}
}
interface AbstractFactory {
Product1 create1();
Product2 create2();
}
interface Product1 {
void show();
}
interface Product2 {
void show();
}
class AbstractFactoryImpl implements AbstractFactory {
@Override
public Product1 create1() {
System.out.println("创建第一个产品");
return new ProductImpl1();
}
@Override
public Product2 create2() {
System.out.println("创建第二个产品");
return new ProductImpl2();
}
}
class ProductImpl1 implements Product1 {
@Override
public void show() {
System.out.println("展示第一个产品");
}
}
class ProductImpl2 implements Product2 {
@Override
public void show() {
System.out.println("展示第二个产品");
}
}
4、建造者模式()
主要用来通过链式调用生成不同的配置。
结构:
产品、抽象建造者、具体建造者、指挥者
使用案例:StringBuilder().append().append()....链式调用 (简化)
生活案例:生成不同配置的电脑,不同的套餐等。
package com.mainwood.designdemo.builder;
/**
* @author qmai 抽象建造者
*/
public interface Builder {
/**
* 品牌
*
* @param
* @author renxu
* @date 2022/3/25 15:40
* @returns
**/
void brand();
/**
* 规格配置
*
* @param
* @author renxu
* @date 2022/3/25 15:41
* @returns
**/
void setting();
/**
* 尺寸
*
* @param
* @author renxu
* @date 2022/3/25 15:41
* @returns
**/
void size();
}
package com.mainwood.designdemo.builder;
/**
* @author qmai
*/
public class MacBuilder implements Builder{
/**
* 品牌
*
* @author renxu
* @date 2022/3/25 15:40
* @returns
**/
@Override
public void brand() {
System.out.println("系统品牌 mac");
}
/**
* 规格配置
*
* @author renxu
* @date 2022/3/25 15:41
* @returns
**/
@Override
public void setting() {
System.out.println("处理器配置 M1 PRO");
}
/**
* 尺寸
*
* @author renxu
* @date 2022/3/25 15:41
* @returns
**/
@Override
public void size() {
System.out.println("屏幕尺寸 13.3寸");
}
}
package com.mainwood.designdemo.builder;
/**
* @author qmai
*/
public class WindowsBuilder implements Builder{
/**
* 品牌
*
* @author renxu
* @date 2022/3/25 15:40
* @returns
**/
@Override
public void brand() {
System.out.println("系统品牌 windows");
}
/**
* 规格配置
*
* @author renxu
* @date 2022/3/25 15:41
* @returns
**/
@Override
public void setting() {
System.out.println("处理器配置 i9-12008HK");
}
/**
* 尺寸
*
* @author renxu
* @date 2022/3/25 15:41
* @returns
**/
@Override
public void size() {
System.out.println("屏幕尺寸 15.6寸");
}
}
package com.mainwood.designdemo.builder;
/**
* @author qmai
*/
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void make(){
builder.brand();
builder.setting();
builder.size();
}
}
5、原型模式()
深克隆:与原对象地址不同
创建型------分割线------结构型
6、适配器模式
spring中使用:前端控制器中的DispatcherServlet
目标对象:需要调用其他对象的对象
适配对象:被调用的对象
适配器:适配两者的对象
目标对象:要为接口或者抽象类
适配对象:有自己的方法
适配器:要实现或继承目标对象,聚合适配对象,有自己的有参构造函数去执行适配者的方法
public class AdapterDemo {
public static void main(String[] args) {
ElectricMachine electricMachine = new ElectricMachine110();
Switch aSwitch = new Adpater(electricMachine);
aSwitch.open();
}
}
//适配者接口
interface ElectricMachine {
public void start();
}
//适配者实体
class ElectricMachine110 implements ElectricMachine {
@Override
public void start() {
System.out.println("打开110V电器电器");
}
}
//目标对象接口
interface Switch {
public void open();
}
//目标对象实体
class SwitchImpl implements Switch {
@Override
public void open() {
;
}
}
//适配器
class Adpater implements Switch {
private ElectricMachine electricMachine;
public Adpater(ElectricMachine electricMachine) {
this.electricMachine = electricMachine;
}
@Override
public void open() {
electricMachine.start();
}
}
7、代理模式
spring中使用:AOP
结构:
抽象主题:被代理对象的接口或实体类
真实主题:被代理对象实体类
代理类:代理类
关系:代理类要去实现或继承抽象主题,聚合真是主题的被代理类,在代理类中自己写入增强方法区增强原方法。
动态代理与静态代理的主要区别在于:
只是主题是否预先存在,存在使用静态代理,不存在使用动态代理。
public class ProxyDemo {
public static void main(String[] args) {
Car car = new ProxyCar();
car.drive();
}
}
interface Car {
void drive();
}
class RealCar implements Car {
@Override
public void drive() {
System.out.println("车子启动");
}
}
class ProxyCar implements Car {
RealCar car = new RealCar();
@Override
public void drive() {
before();
car.drive();
after();
}
void before() {
System.out.println("打火");
}
void after() {
System.out.println("松刹车");
}
}
8、装饰器模式
对原有对象正增加一些新功能
结构:
抽象构建:定义的抽象接口
具体构建:集体的实现接口
抽象装饰:实现抽象接口,并聚合具体构建
具体装饰:继承抽象装饰,并扩展方法
public class DecoratorDemo {
public static void main(String[] args) {
Shape three = new ThreeShape();
Shape four = new FourShape();
AbDecorator t = new DecoratorImpl(three);
AbDecorator f = new DecoratorImpl(four);
t.draw();
f.draw();
}
}
interface Shape {
void draw();
}
class ThreeShape implements Shape {
@Override
public void draw() {
System.out.println("画三角形");
}
}
class FourShape implements Shape {
@Override
public void draw() {
System.out.println("画四边形");
}
}
abstract class AbDecorator implements Shape {
public Shape shape;
public AbDecorator(Shape shape) {
this.shape = shape;
}
@Override
public void draw() {
shape.draw();
}
}
class DecoratorImpl extends AbDecorator {
public DecoratorImpl(Shape shape) {
super(shape);
}
@Override
public void draw() {
shape.draw();
otherFun(shape);
}
//扩展方法
public void otherFun(Shape shape) {
System.out.println(shape + " 的增加方法");
}
}
9、桥接模式()
10、外观模式
11、组合模式
12、享元模式
结构型------分割线-------行为型
13、策略模式
根据不同的参数执行不同的策略
结构:
抽象策略:提供策略接口的方法,
具体策略:提供策略的具体实现
环境:聚合具体策略,并提供一个执行策略的方法的方法
public class StrategyDemo {
public static void main(String[] args) {
Tool plane = new ByPlane();
Tool car = new ByCar();
Context s1 = new Context(plane);
Context s2 = new Context(car);
s1.exec();
s2.exec();
}
}
//抽象策略接口
interface Tool{
void travel();
}
class ByPlane implements Tool{
@Override
public void travel() {
System.out.println("坐飞机出行");
}
}
class ByCar implements Tool{
@Override
public void travel() {
System.out.println("开车出行");
}
}
class Context {
private Tool tool;
public Tool getTool() {
return tool;
}
public void setTool(Tool tool) {
this.tool = tool;
}
public Context(Tool tool){
this.tool = tool;
}
public void exec(){
tool.travel();
}
}
14、模板方法模式
根据抽象类中的固定方法,去执行抽象方法,抽象方法由子类进行重写来供后期调用
抽象类:提供模板方法和抽象方法
具体子类:重写抽象类的抽象方法
public class TemplateDemo {
public static void main(String[] args) {
Template worker = new Worker();
Template student = new Student();
worker.exec();
student.exec();
}
}
abstract class Template {
//模板方法
void exec() {
setJob();
setAge();
setGender();
}
abstract void setJob();
abstract void setAge();
abstract void setGender();
}
class Worker extends Template {
@Override
void setJob() {
System.out.println("我是工人");
}
@Override
void setAge() {
System.out.println("我20岁");
}
@Override
void setGender() {
System.out.println("我是男士");
}
}
class Student extends Template {
@Override
void setJob() {
System.out.println("我是学生");
}
@Override
void setAge() {
System.out.println("我10岁");
}
@Override
void setGender() {
System.out.println("我是女生");
}
}