文章目录
前言
1995 年,GoF(Gang of Four,四人组/四人帮)合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了 23 种设计模式,从此树立了软件设计模式领域的里程碑,人称「GoF设计模式」。
一、设计模式是什么?
设计模式(Design Pattern) 是前辈们对代码开发经验的总结,是解决特定问题的一系列套路,他不是语法规定,而是一种套用实现代码的可复用性,可维护性,可读性,稳健性以及安全性的解决方案。
GOF23(23种设计模式)
二、为什么使用设计模式
1. 使用设计模式的优点:
可以提高程序员的思维能力,编程能力 和 设计能力
使程序设计更加标准化,代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期
使软件代码可重用性高,可读性强,灵活性好,可维护性强
GOF 23
一种思维 一种进步 一种态度
2. 23种设计模式
创建型模式:
单例模式 工厂模式 抽象工厂模式 建造者模式 原型模式
结构性模式:
适配器模式 桥接模式 装饰模式 组合模式i 外观模式 享元模式 代理模式
行为型模式:
模板方法模式 命令模式 迭代器模式 观察者模式 中介者模式 备忘录模式 解释器模式 状态模式
策略模式 职责链模式 访问者模式
代码如下(示例):
三、先了解一下OOP七大原则(面向对象的七大原则)
三、来吧 单例模式
单例模式核心思想:不要去new一个对象
可以先设想一下,在王者峡谷里大龙是不是唯一的,当一群人一一打他的的时候,他是在持续掉血的。大龙就是个唯一的对象,如果每个人去到打大龙的事后都各自new一个大龙的对象的话,就相当于打的不是一条龙,
就好比
那什男爵(大龙):10000血
剑豪 (攻击力 :200)->攻击 大龙(血量剩余:9800)
剑剑圣 (攻击力 :300)->攻击 大龙(血量剩余:9500)
这是正常情况
-------如果每个人new一个大龙对象的话—效果是这样-----
那什男爵(大龙):10000血
剑豪 (攻击力 :200)->攻击 大龙(血量剩余:9800)
剑剑圣 (攻击力 :300)->攻击 大龙(血量剩余:9700)
2.代码演示一下
演示前介绍一下创建单例的两种方式
饿汉式
是立即加载的方式,无论是否会用到这个对象,都会加载。
如果在构造方法里写了性能消耗较大,占时较久的代码,比如建立与数据库的连接,那么就会在启动的时候感觉稍微有些卡顿。
懒汉式
是延迟加载的方式,只有使用的时候才会加载。 并且有线程安全的考量
使用懒汉式,在启动的时候,会感觉到比饿汉式略快,因为并没有做对象的实例化。 但是在第一次调用的时候,会进行实例化操作,感觉上就略慢。
看业务需求,如果业务上允许有比较充分的启动和初始化时间,就使用饿汉式,否则就使用懒汉式
代码如下(示例):
单例模式(懒汉模式)
package charactor;
public class GiantDragon {
//私有化构造方法使得该类无法在外部通过new 进行实例化
private GiantDragon(){
}
//准备一个类属性,用于指向一个实例化对象,但是暂时指向null
private static GiantDragon instance;
//public static 方法,返回实例对象
public static GiantDragon getInstance(){
//第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象
if(null==instance){
instance = new GiantDragon();
}
//返回 instance指向的对象
return instance;
}
}
单例模式(懒汉模式)
package charactor;
public class GiantDragon {
//私有化构造方法使得该类无法在外部通过new 进行实例化
private GiantDragon(){
}
//准备一个类属性,用于指向一个实例化对象,但是暂时指向null
private static GiantDragon instance;
//public static 方法,返回实例对象
public static GiantDragon getInstance(){
//第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象
if(null==instance){
instance = new GiantDragon();
}
//返回 instance指向的对象
return instance;
}
}
测试输出
(可以清晰地看出,调用的对象都是同一个对象,是唯一的)
package charactor;
public class TestGiantDragon {
public static void main(String[] args) {
//通过new实例化会报错
// GiantDragon g = new GiantDragon();
//只能通过getInstance得到对象
GiantDragon g1 = GiantDragon.getInstance();
GiantDragon g2 = GiantDragon.getInstance();
GiantDragon g3 = GiantDragon.getInstance();
//都是同一个对象
System.out.println(g1==g2);
System.out.println(g1==g3);
}
}
面试长问:
什么是单例模式?
回答的时候,要答到三元素
- 构造方法私有化
- 静态属性指向实例
- public static的 getInstance方法,返回第二步的静态属性
四、工厂模式
工厂模式:核心思想(创建者和调用者的分离1.实例化不用new,用工厂方法替代2.将选择实现类,创建对象统一管理控制。从而将调用者跟我们的实现类解耦)
应满足原则:开闭原则 依赖倒转原则 迪米特法则
简单工厂:
方法接口:
//Car接口
package com.test.giaoge;
public interface Car {
void name();
}
接口定义:
package com.test.giaoge;
public class TeSiLa implements Car {
@Override
public void name() {
System.out.println("特斯拉--不是哥斯拉");
}
}
package com.test.giaoge;
public class WuLing implements Car {
@Override
public void name() {
System.out.println("五菱宏光欢迎您");
}
}
创建工厂:
package com.test.giaoge;
//静态工厂模式
//(存在弊端你,当增加一个商品时,如果不修改代码,做不到)
public class CarFactory {
//方法一:
public static Car getcar(String car){
if(car.equals("五菱")){
return new WuLing();
}else if(car.equals("特斯拉")){
return new TeSiLa();
}else{
return null;
}
}
//方法二
public static Car getWuLi(){
return new WuLing();
}
public static Car getTeSiLa(){
return new TeSiLa();
}
}
测试输出:
package com.test.giaoge;
import java.util.concurrent.Callable;
public class Costomer {
public static void main(String[] args) {
//传统方式下
Car wlcar=new WuLing();
Car tscar=new TeSiLa();
wlcar.name();
tscar.name();
//方法一测试:
Car wlcar3=CarFactory.getcar("五菱");
Car tscar4=CarFactory.getcar("特斯拉");
wlcar3.name();
tscar4.name();
//方式二:
Car wlcar5=CarFactory.getWuLi();
Car tscar6=CarFactory.getTeSiLa();
wlcar5.name();
tscar6.name();
}
}
我们直接去工厂去拿,不用new,不用考虑内部的复杂过程;
这种简单工厂的模式对功能的扩展不是很方便所以我们接下来讲一下
工厂方法模式
去除前面的carFactory 类
创建CarFactory接口
package com.test.method;
public interface CarFactory {
Car getCart();
}
创建各种车工场
package com.test.method;
public class TeSiLaFactory implements CarFactory{
@Override
public Car getCart() {
return new TeSiLa();
}
}
package com.test.method;
public class WuLiFactory implements CarFactory {
@Override
public Car getCart() {
return new WuLing();
}
}
测试
package com.test.method;
import com.test.giaoge.CarFactory;
//工厂方法模式
public class Costomer {
public static void main(String[] args) {
new TeSiLaFactory().getCart().name();
new WuLiFactory().getCart().name();
}
}
这种方式呢 当我们要扩展大众车型系列时 就不会涉及到开闭原则所限制的问题
扩展功能直接创建 相应的车型Factory工厂即可 不会涉及开闭原则问题