设计模式介绍
1.简介
一共分为23种设计模式
创建型模式(5种):怎么进行对象的创建,让对象的创建和使用分离
结构型模式(7种):将对象或者类按照某种模式或者布局组成更大的结构,用于拼装类
行为型模式(11种):描述类或者对象之间怎么进行相互协作,完成单个对象无法完成的任务,主要是对职责的划分,类之间的相互协作
2.面向对象的七大原则
3.设计模式具体分类
创建型模式
3.1 单例模式
3.1.1 饿汉式
存在问题:
资源浪费
//饿汉式
public class Hungry {
//缺点是类一加载,该类中的资源同步加载,造成资源浪费
private byte[] data1 = new byte[3];
private byte[] data2 = new byte[3];
private byte[] data3 = new byte[3];
private byte[] data4 = new byte[3];
//构造方法私有
private Hungry() {
}
//直接构造一个final本身
private final static Hungry HUNGRY = new Hungry();
//对外提供获取本类的方法
public static Hungry getInstance() {
return HUNGRY;
}
}
3.1.2 懒汉式–DCL懒汉式
存在问题:
lazyMan = new LazyMan();不是原子性操作,存在指令重排
package single;
//懒汉式
public class LazyMan {
//私有构造
private LazyMan() {
System.out.println(Thread.currentThread().getName());
}
//需要时再做构造
private static LazyMan lazyMan;
//单线程下模式
public static LazyMan getInstance() {
if (lazyMan == null) {
lazyMan = new LazyMan();
}
return lazyMan;
}
//多线程下方式
public static LazyMan getInstanceT() {
if (lazyMan == null) {
synchronized (LazyMan.class) {
if (lazyMan == null) {
lazyMan = new LazyMan();
}
}
}
return lazyMan;
}
//多线程检测
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
LazyMan.getInstance();
}).start();
}
}
}
解决指令重排—存在问题:暴力反射破坏单例模式
private static volatile LazyMan lazyMan;
package single;
//懒汉式
public class LazyMan {
//私有构造
private LazyMan() {
System.out.println(Thread.currentThread().getName());
}
//需要时再做构造
private static volatile LazyMan lazyMan;
//单线程下模式
public static LazyMan getInstance() {
if (lazyMan == null) {
lazyMan = new LazyMan();
}
return lazyMan;
}
//多线程下方式
public static LazyMan getInstanceT() {
if (lazyMan == null) {
synchronized (LazyMan.class) {
if (lazyMan == null) {
lazyMan = new LazyMan();
}
}
}
return lazyMan;
}
//多线程检测
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
LazyMan.getInstance();
}).start();
}
}
}
3.1.3静态内部类方式
package single;
public class Holder {
private Holder(){
}
public static Holder getInstance(){
return InnerClass.HOLDER;
}
public static class InnerClass{
private static final Holder HOLDER = new Holder();
}
}
3.1.4枚举类型安全模式
上述的模式都是不安全的,如果暴力反射会破坏单例模式,解决方式是查看暴力反射中存在说明,无法反射枚举类型
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance(){
return EnumSingle.INSTANCE;
}
}
3.2 工厂模式
作用:实现创建者和调用者的分离
核心本质:
实力化对象不使用new,用工厂方法代替
将选择实现类,创建对象统一管理和控制。从而将调用跟实现类解耦
详细分类:
- 简单工厂模式
- 用来生产同一等级结构中的任意产品,对于增加新的产品,需要覆盖已有代码。
- 工厂方法模式
- 用来生产同一等级结构中的固定产品,支持增加任意产品
- 抽象工厂模式
- 围绕一个超级工厂创建其他工厂。该工厂又被称为其他工厂的工厂。
3.2.1 简单工厂模式
弊端:每次新增一个类型都需要修改原来的代码
原始方法:
public interface Car {
void name();
}
public class Telsa implements Car {
@Override
public void name() {
System.out.println("特斯拉");
}
}
public class WuLing implements Car {
@Override
public void name() {
System.out.println("五菱宏光");
}
}
package factory.simple.test;
import factory.simple.Car;
import factory.simple.Telsa;
import factory.simple.WuLing;
public class Consumer {
public static void main(String[] args) {
//原始方法
Car car1 = new WuLing();
Car car2 = new Telsa();
car1.name();
car2.name();
}
}
工厂模式方法
package factory.simple.test;
import factory.simple.Car;
import factory.simple.CarFactory;
import factory.simple.Telsa;
import factory.simple.WuLing;
public class Consumer {
public static void main(String[] args) {
//原始方法
Car car1 = new WuLing();
Car car2 = new Telsa();
car1.name();
car2.name();
//简单工厂方法
Car car = CarFactory.getCar("五菱");
car.name();
}
}
调用
package factory.simple.test;
import factory.simple.Car;
import factory.simple.CarFactory;
import factory.simple.Telsa;
import factory.simple.WuLing;
public class Consumer {
public static void main(String[] args) {
//简单工厂方法
Car car = CarFactory.getCar("五菱");
car.name();
}
}
3.2.2 工厂方法模式
package factory.method.factory;
import factory.method.demo.Car;
public interface CarFactory {
Car getcar();
}
package factory.method.factory;
import factory.method.demo.Car;
import factory.method.demo.Telsa;
public class TelsaFactory implements CarFactory {
@Override
public Car getcar() {
return new Telsa();
}
}
package factory.method.factory;
import factory.method.demo.Car;
import factory.method.demo.WuLing;
public class WuLingFactory implements CarFactory {
@Override
public Car getcar() {
return new WuLing();
}
}
新增类型时,只需要实现接口扩展实现类
3.3 抽象工厂模式
定义:
抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类
适用场景:
- 应用等不依赖于产品类实例如何被创建,实现等细节
- 强调一系列相关的产品对象,一起使用创建对象需要大量的 重复代码
- 提供一个产品类的库,所有产品以同样的接口出现,从而使得应用层不依赖于具体的实现
优点:
- 具体产品在应用层的代码隔离,无需关心创建的细节
- 将一系列的产品统一到一起创建
缺点: - 规定了所有可能被创建的产品集合,产品扩展困难
- 增加了系统的抽象性和理解难度
package abstrac;
public interface Phone {
void start();
void shutdown();
void callup();
void sendMS();
}
package abstrac;
public class XiaoMiPhone implements Phone {
@Override
public void start() {
System.out.println("打开小米");
}
@Override
public void shutdown() {
System.out.println("关闭小米");
}
@Override
public void callup() {
System.out.println("小米打电话");
}
@Override
public void sendMS() {
System.out.println("小米发短信");
}
}
package abstrac;
public class HuaWeiPhone implements Phone {
@Override
public void start() {
System.out.println("打开华为");
}
@Override
public void shutdown() {
System.out.println("关闭华为");
}
@Override
public void callup() {
System.out.println("华为打电话");
}
@Override
public void sendMS() {
System.out.println("华为发短信");
}
}
package abstrac;
public interface IRouterProduct {
void start();
void shutdown();
void openWifi();
void setting();
}
package abstrac;
public class XiaoMiRouter implements IRouterProduct {
@Override
public void start() {
System.out.println("打开小米路由");
}
@Override
public void shutdown() {
System.out.println("关闭小米路由");
}
@Override
public void openWifi() {
System.out.println("小米打开wifi");
}
@Override
public void setting() {
System.out.println("小米路由设置");
}
}
package abstrac;
public class HuaWeiRouter implements IRouterProduct {
@Override
public void start() {
System.out.println("打开华为路由");
}
@Override
public void shutdown() {
System.out.println("关闭华为路由");
}
@Override
public void openWifi() {
System.out.println("华为打开wifi");
}
@Override
public void setting() {
System.out.println("华为路由设置");
}
}
package abstrac;
public interface IProductFactory {
//生产手机
Phone phoneProduct();
//生产路由
IRouterProduct routerroduct();
}
package abstrac;
public class XiaoMiProductFactory implements IProductFactory {
@Override
public Phone phoneProduct() {
return new XiaoMiPhone();
}
@Override
public IRouterProduct routerroduct() {
return new XiaoMiRouter();
}
}
package abstrac;
public class HuaWeiProducerFactory implements IProductFactory {
@Override
public Phone phoneProduct() {
return new HuaWeiPhone();
}
@Override
public IRouterProduct routerroduct() {
return new HuaWeiRouter();
}
}
package abstrac.test;
import abstrac.HuaWeiProducerFactory;
import abstrac.IRouterProduct;
import abstrac.Phone;
import abstrac.XiaoMiProductFactory;
public class Consumer {
public static void main(String[] args) {
System.out.println("小米产品=========");
XiaoMiProductFactory xiaoMiProductFactory = new XiaoMiProductFactory();
Phone xiaomiPhone = xiaoMiProductFactory.phoneProduct();
IRouterProduct xiaomiRouterroduct = xiaoMiProductFactory.routerroduct();
xiaomiPhone.sendMS();
xiaomiRouterroduct.setting();
System.out.println("华为产品=====");
HuaWeiProducerFactory huaWeiProducerFactory = new HuaWeiProducerFactory();
Phone huaWeiPhone = huaWeiProducerFactory.phoneProduct();
IRouterProduct huawwiRouterroduct = huaWeiProducerFactory.routerroduct();
huaWeiPhone.callup();
huawwiRouterroduct.openWifi();
}
}
3.4建造者模式
提供了创建对象的最佳方式
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
作用:在用户不知道对象的建造过程和细节的情况下可以直接创建复杂的对象
用户只需要给出指定复杂的对象类型和内容,建造者模式负责顺序创建复杂对象,把内部的建造过程和细节隐藏。
package build;
public abstract class Builder {
abstract void build1();//步骤1
abstract void build2();//步骤2
abstract void build3();//步骤3
abstract void build4();//步骤4
abstract void build5();//步骤5
abstract Product getProduct();
}
package build;
//指导具体的worker按照一定的工作顺序进行建造
public class Director {
public Product build(Builder builder){
builder.build1();
builder.build2();
builder.build3();
builder.build4();
builder.build5();
return builder.getProduct();
}
}
package build;
public class Product {
private String build1;
private String build2;
private String build3;
private String build4;
private String build5;
public String getBuild1() {
return build1;
}
public void setBuild1(String build1) {
this.build1 = build1;
}
public String getBuild2() {
return build2;
}
public void setBuild2(String build2) {
this.build2 = build2;
}
public String getBuild3() {
return build3;
}
public void setBuild3(String build3) {
this.build3 = build3;
}
public String getBuild4() {
return build4;
}
public void setBuild4(String build4) {
this.build4 = build4;
}
public String getBuild5() {
return build5;
}
public void setBuild5(String build5) {
this.build5 = build5;
}
@Override
public String toString() {
return
build1 + '\n' +
build2 + '\n' +
build3 + '\n' +
build4 + '\n' +
build5 + '\n';
}
}
package build;
public class Worker extends Builder {
private Product product;
public Worker() {
product = new Product();
}
@Override
void build1() {
product.setBuild1("步骤一");
}
@Override
void build2() {
product.setBuild2("步骤二");
}
@Override
void build3() {
product.setBuild3("步骤三");
}
@Override
void build4() {
product.setBuild4("步骤四");
}
@Override
void build5() {
product.setBuild5("步骤五");
}
@Override
Product getProduct() {
return product;
}
}
package build.test;
import build.Director;
import build.Product;
import build.Worker;
public class Consumer {
public static void main(String[] args) {
Director director = new Director();
Product build = director.build(new Worker());
System.out.println(build.toString());
}
}
自定义类型的建造者
package build1;
public abstract class Builder {
//按照传入的信息进行创建
public abstract Builder build1(String msg);//步骤1
public abstract Builder build2(String msg);//步骤2
public abstract Builder build3(String msg);//步骤3
public abstract Builder build4(String msg);//步骤4
public abstract Builder build5(String msg);//步骤5
public abstract Product getProduct();
}
package build1;
public class Product {
private String build1="内容一";
private String build2="内容二";
private String build3="内容三";
private String build4="内容四";
private String build5="内容五";
public String getBuild1() {
return build1;
}
public void setBuild1(String build1) {
this.build1 = build1;
}
public String getBuild2() {
return build2;
}
public void setBuild2(String build2) {
this.build2 = build2;
}
public String getBuild3() {
return build3;
}
public void setBuild3(String build3) {
this.build3 = build3;
}
public String getBuild4() {
return build4;
}
public void setBuild4(String build4) {
this.build4 = build4;
}
public String getBuild5() {
return build5;
}
public void setBuild5(String build5) {
this.build5 = build5;
}
@Override
public String toString() {
return
build1 + '\n' +
build2 + '\n' +
build3 + '\n' +
build4 + '\n' +
build5 + '\n';
}
}
package build1;
public class Worker extends Builder {
private Product product;
public Worker() {
this.product = new Product();
}
@Override
public Builder build1(String msg) {
product.setBuild1(msg);
return this;
}
@Override
public Builder build2(String msg) {
product.setBuild2(msg);
return this;
}
@Override
public Builder build3(String msg) {
product.setBuild3(msg);
return this;
}
@Override
public Builder build4(String msg) {
product.setBuild4(msg);
return this;
}
@Override
public Builder build5(String msg) {
product.setBuild5(msg);
return this;
}
@Override
public Product getProduct() {
return product;
}
}
package build1.test;
import build1.Worker;
public class Consumer {
public static void main(String[] args) {
Worker worker = new Worker();
System.out.println(worker.getProduct());
worker.build1("内容六");
System.out.println(worker.getProduct());
}
}
3.5 原型模式
以原有的对象为模型进行复制
package prototype;
public class Sheep implements Cloneable {
private String name;
private Integer age;
public Sheep() {
}
public Sheep(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package prototype;
public class Farm {
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sheep1 = new Sheep("sheep1", 3);
System.out.println(sheep1.toString());
System.out.println(sheep1.hashCode());
//克隆
Sheep sheep2 = (Sheep) sheep1.clone();
System.out.println(sheep2.toString());
System.out.println(sheep2.hashCode());
}
}
存在的问题:这样的克隆属于浅克隆,当修改对象2的属性时候,1的属性也被修改了,原因是克隆时只是克隆了属性的引用地址
实现深克隆,即对象间属性不干扰
package prototype;
import java.util.Date;
public class Sheep implements Cloneable {
private String name;
private Integer age;
private Date date;
public Sheep() {
}
public Sheep(String name, Integer age, Date date) {
this.name = name;
this.age = age;
this.date = date;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Sheep clone = (Sheep) super.clone();
clone.date = (Date) this.date.clone();
return clone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", date=" + date +
'}';
}
}
package prototype;
import java.util.Date;
public class Farm {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date(232323);
Sheep sheep1 = new Sheep("sheep1", 3,date);
System.out.println(sheep1.toString());
System.out.println(sheep1.hashCode());
//克隆
Sheep sheep2 = (Sheep) sheep1.clone();
System.out.println(sheep2.toString());
System.out.println(sheep2.hashCode());
sheep2.setDate(new Date(454545));
System.out.println(sheep1.getDate());
System.out.println(sheep2.getDate());
}
}
结构型模式:从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题
3.6适配器模式
将一个类的接口转换成用户希望的或者可以用的接口
package adapter;
/**
* 要被适配的类,类似网线
*/
public class NetLine {
public void request(){
System.out.println("已连接到网线");
}
}
package adapter;
/**
* 转接的类,定义接口,可以实现不同的转接形式
*/
public interface TraceType {
//处理请求,将typeC转换成网线插口
public void handlerRequest();
}
package adapter;
public class TraceToNet implements TraceType {
private NetLine netLine;
public TraceToNet(NetLine netLine) {
this.netLine = netLine;
}
@Override
public void handlerRequest() {
netLine.request();
}
}
package adapter;
/**
* 客户端类:主体电脑,但无法直接使用Adapter
*/
public class Computer {
//需要连接上网的功能,需要借助其他工具连接到Adapter
public void net(TraceType traceType){
traceType.handlerRequest();
}
}
package adapter.test;
import adapter.NetLine;
import adapter.Computer;
import adapter.TraceToNet;
public class CommonTest {
public static void main(String[] args) {
Computer computer = new Computer();//定义电脑
NetLine netLine = new NetLine();//定义网线
TraceToNet traceToNet = new TraceToNet(netLine);//定义转换器
computer.net(traceToNet);
}
}
输出结果:
3.7 桥接模式
桥接模式时将抽象部分与它的实现部分分离,是他们可以独立变化,它是一种对象结构型模式,又被称为柄体模式或接口模式
实现场景:当多个维度出现,需要实现多层继承,代码可扩展性低
package bridge;
/**
* 定义一个品牌
*/
public interface Brand {
void info();
}
package bridge;
public class Apple implements Brand {
@Override
public void info() {
System.out.print("Apple品牌");
}
}
package bridge;
public class HuaWei implements Brand {
@Override
public void info() {
System.out.print("华为品牌");
}
}
package bridge;
public abstract class Computer {
//受保护的变量,可以继承 桥
protected Brand brand;
public Computer(Brand brand) {
this.brand = brand;
}
public void info(){
brand.info();
}
}
package bridge;
//增加品牌下的东西
public class DeskTop extends Computer{
public DeskTop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.println("台式机");
}
}
package bridge;
//笔记本
public class LapTop extends Computer{
public LapTop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.println("笔记本");
}
}
package bridge.test;
import bridge.*;
public class Test {
public static void main(String[] args) {
//苹果笔记本
Computer computer = new LapTop(new Apple());
computer.info();
//华为台式机
DeskTop deskTop = new DeskTop(new HuaWei());
deskTop.info();
}
}
结果:
3.8
3.9
3.10
3.11
3.12
3.13
3.14
3.15
3.16
3.17
3.18
3.19
3.20
3.21
3.22
3.23
*******************************************补充中