Unit12 设计模式 部分学习笔记
Part 1:
1、什么是设计模式?
- 答:设计模式(Design
pattern)是代表的是解决问题的通用方法、套路,是开发经验的总结。
2、Java中设计模式有多少种?
- 答:共23种设计模式。
- 分为三类:创建型、结构型、行为型。
- 参考资源: 《Java与模式》、GoF《设计模式》、《Head First设计模式》、菜鸟教程:https://www.runoob.com/design-pattern/design-pattern-tutorial.html
- http://c.biancheng.net/view/1348.html
3、设计模式什么场合使用?
- 答:一般在框架里用的很多,比如:Spring框架。
4、面试题:请列举几个Java设计模式。
- 模板方法模式、单例模式、简单工厂模式、工厂方法模式、适配器模式、装饰模式、观察者模式、MVC模式。
Part2 单例模式 (非常重要)
- 创建型模式
1.解决什么问题?
- 一个类只能创建一个对象。
2.什么时候用?
- 只需要单一对象的时候。比如:帮助–窗口。
3.实现方式:共2种
- (1)饿汉式:单例模式类被加载的时候,单例对象就已经被创建。线程安全、效率较高。
- 1.属性:private、static修饰、当前类类型、要初始化,且显式赋值
- 2.构造方法:构造方法被private修饰
- 3.提供:公共、静态方法、返回当前类对象(实例)
- 饿汉式程序示例:
public class MonitorEager {
public static void main(String[] args) {
Monitor m1 = Monitor.getInstance();//第一次得到班长对象
Monitor m2 = Monitor.getInstance();//第二次得到班长对象
System.out.println(m1.getName());//m1和m2是同一个人吗?
System.out.println(m2.getName());
System.out.println(m1 == m2);//m1和m2地址一样吗?
}
}
class Monitor {
String name;
//1.属性:私有、静态、当前类类型
private static Monitor monitor = new Monitor("李楠");
//2.构造方法私有
private Monitor(String name) {
this.name = name;
}
//3.提供公共、静态方法得到当前类对象
public static Monitor getInstance() {
return monitor;
}
public String getName() {
return name;
}
}
- (2)懒汉式:当程序第一次访问单例模式对象时才进行创建。非线程安全、效率较低。
- 1.属性:私有、静态、当前类类型、默认值null
- 2.构造方法:私有private
- 3.提供:公共、静态方法(if判断,是null就创建对象并初始化属性;否则直接返回)、返回当前类对象
public class MonitorLazy {
public static void main(String[] args) {
MonitorL ml1 = MonitorL.getInstance();//得到第一个班长
MonitorL ml2 = MonitorL.getInstance();//得到第一个班长
System.out.println(ml1.getName());
System.out.println(ml2.getName());
System.out.println(ml1 == ml2);//ml1和ml2是同一个人吗?
}
}
class MonitorL {
private String name;
private static MonitorL mon;//没有new对象赋值,默认值是null
private MonitorL(String name) {
this.name = name;
}
public static MonitorL getInstance() {
if (mon == null) {
mon = new MonitorL("张三");
}
return mon;
}
public String getName() {
return name;
}
}
- 二者区别:给属性赋值的时间不同,饿汉式直接显式赋值;懒汉式推迟到了方法中赋值。
4.如何选择?
- 如果单例模式对象在系统中经常会被用到,饿汉式是首选,无需考虑线程安全问题。效率较高。
- 如果单例模式在系统中会很少用到或者几乎不会用到,可以懒汉式。效率较低。
Part 3 模板方法模式 Template Method
- 行为型模式
- 我们以软件公司员工上班为例,每个人上班打卡、做当天工作、下班打卡,这个流程是不变的,但是具体做什么工作,根据该员工的岗位来确定;程序员写代码,HR看简历约面试,项目经理写文档、与客户沟通,他们三人的工作内容是不同的,以下是类图及代码实现:
- 抽象类、父类:Employee,里面有抽象方法work(),
- 程序员类,继承Employee,实现Employee中的抽象方法work()
- HR类,继承Employee,实现Employee中的抽象方法work()
- 项目经理类,继承Employee,实现其中的work()抽象方法
- 测试类
1、为什么使用模板方法模式?模板方法模式是什么?
- 设计一个系统时知道了算法(逻辑)所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还不能确定,此时可以使用该模式。
- 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
2、代码实现
- 父类是抽象的(里边有抽象方法,就是模板)
- 抽象方法交给子类实现(子类重写那个抽象方法)
3、特点
- 它封装了代码不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
- 它在父类中提取了公共的部分代码,便于代码复用。
- 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
Part 4 工厂模式 Factory Pattern
1.什么是工厂模式?
- 答:向用户屏蔽创建对象的细节,直接取对象即可。比如:我们去手机店买手机,不需了解手机是如何生产的。
2.使用工厂模式的最终目的
- 创建者和调用者的分离
3.工厂模式的分类:
(1).简单工厂模式:
- 创建型模式,生产的产品相对固定的情况下比较适用
- 基本思想:对象使用者和创建者由不同的人来做,两者分离
- 以生产手机为例,手机工厂只生产华为和ViVo手机,类图如下:
- MobileFactory是工厂类,里面的方法根据参数类型生成不同的手机 Mobile是手机接口
- ViVo、HuaWei手机类,TestSimpleFactoryMobile是工厂的使用者,使用MobileFactory工厂类 手机接口:Mobile
- 手机工厂类:MobileFactory
- ViVo手机类
- HuaWei手机类
- 使用工厂的类,对象使用者和对象的创建者分离,各司其职,明确分工
- 如果新增OPPO手机,需要修改已有代码,不符合“开闭原则”,工厂方法模式解决这个问题
(2).工厂方法模式:
- 创建型模式,定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
- 相比简单工程模式,增加新的工厂类HuaWeiFactory和VivoFactory 手机接口:Mobile
-
手机工厂接口:MobileFactory
-
华为手机工厂类:HuaWeifactory,实现MobileFactory接口 华为手机类HuaWei
-
ViVo手机工厂类: ViVo手机类
-
使用者
-
工厂方法模式好处:用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改;以后如果再增加苹果手机,只需要增加一个类AppleFactory实现MobileFactory接口即可。符合了OCP开闭原则, 不用在原来的代码上修改,只需新增类即可,更好扩展。
(3).抽象工厂模式:
- 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
4.OOP编程七大原则 https://www.cnblogs.com/princessd8251/articles/3784949.html
(1)PBP/OBP/OOP的特征
- PBP(基于过程):函数、域与生命周期的概念、函数重载、函数模板、异常处理、范型算法。
- OBP(基于对象):类(接口)、类的生命周期、类模板。
- OOP(面向对象):继承、多态。
- 三个概念步步深入,后者包括前者。其目的是实现软件开发的可重用性,解决软件危机(软件工程思想未引入之前)。
OOP不可避免设计原则的发展与设计模式的产生,这是OOP独具的特征决定的(正如前面所说,特征的产生是由其产生目的决定的)。
(2)OOP的方法论(高内聚、低耦合、易复用)
(3)OOP设计原则:
- OCP(开放封闭原则):软件实体应该扩展开放、修改封闭。
- DIP(依赖倒置原则):摆脱面向过程编程思想中高层模块依赖于低层实现,抽象依赖于具体细节。
- LSP(Liskov替换原则):继承思想的基础。只有当衍生类可以替换掉基类,软件单位的功能不会受到影响时,基类才真正被复用,而衍生类也才能够在基类的基础上增加新的行为
- ISP(接口隔离原则):接口功能单一,避免接口污染。
- SRP(单一职责原则):就一个类而言,应该仅有一个引起它变化的原因。 如果一个类的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会抑止这个类完成其他职责的能力。
- CARP(合成/聚合复用原则):设计模式告诉我们对象委托优于类继承,从UML的角度讲,就是关联关系优于继承关系。尽量使用合成/聚合、尽量不使用继承。
- LoD(迪米特原则或最少知识原则):就是说一个对象应当对其他对象尽可能少的了解。即只直接与朋友通信,或者通过朋友与陌生人通信。
5.使用示例:
- Calendar的getInstance方法:Calendar.getInstance();
- JDBC中Connection对象的获取getConnection方 法:DriverManager.getConnection();
- spring中的IOC容器创建、管理bean对象的时候
- 反射中Class对象的newInstance方法
能少的了解。即只直接与朋友通信,或者通过朋友与陌生人通信。
5.使用示例:
- Calendar的getInstance方法:Calendar.getInstance();
- JDBC中Connection对象的获取getConnection方 法:DriverManager.getConnection();
- spring中的IOC容器创建、管理bean对象的时候
- 反射中Class对象的newInstance方法