一、总览
二、设计的七大原则
2.1 开闭原则
扩展新类而不是修改旧类
2.2 里氏替换原则
继承父类而不去改变父类(继承必须确保超类所拥有的性质在子类中仍然成立,就是要修改父类留给子类的方法,而不是修改覆写父类的方法)
2.3 依赖倒置原则
面向接口编程,而不是面向实现类(写代码时候应该是面向他的接口层去编写,而不去关注具体的实现细节)
2.4 单一职责原则
每个类只负责自己的事情,而不是变成万能
2.5 接口隔离原则
各个类建立自己的专用接口,而不是建立万能接口(A、B两个类应该订一属于各自的接口提供对外实现,而不是把A和B的所有接口放在一个类里面)
2.6 迪米特法则
最少知识原则(无需直接交互的两个类,如果需要交互,使用中间者。例:A依赖B、C、D、E的功能,把B、C、D、E都放在了A里面)
过度使用迪米特法则会使系统产生大量的中介类,从而增加系统的复杂性,使模块之间的通信效率降低
2.7 合成复用原则
优先组合,其次继承(A有两个方法,B有10个,A要用B的方法则直接在A中添加一个属性就是B即可,而不是继承B)
又叫组合/聚合复用原则(Composition/Aggregate Reuse Principle,CARP) 软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现
三、24种模式
3.1 创建型模式
关注“怎样创建出对象?”“将对象的创建与使用分离”。降低系统的耦合度
- 对象的创建由相关的工厂来完成;(各种工厂模式)
- 对象的创建由一个建造者来完成;(建造者模式)
- 对象的创建由原来对象克隆完成;(原型模式)
- 对象始终在系统中只有一个实例;(单例模式)
3.1.1 单例模式
一个单一的类,负责创建自己的对象,同时确保系统中只有单个对象被创建。
- 什么场景用到?
- 多线程中的线程池
- 数据库的连接池
- 系统环境信息
- 上下文(ServletContext)
- ......
懒汉式代码
public class Person {
private String name;
private String age;
//懒汉、饿汉
private volatile static Person instance;
//构造器私有,外部不能实例化
private Person() {
System.out.println("创建了Person");
}
//提供给外部的方法
//1、public static synchronized Person guiguBoss() 锁太大
//2、双重检查锁+内存可见性(设计模式)
public static Person guiguBoss() {
//如果没有再去创建
if (instance == null) {
synchronized (Person.class) {
if(instance == null){
Person person = new Person();
//多线程问题
instance = person;
}
}
}
return instance;
}
}
3.1.2 原型(Prototype)模式
- 原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。
- 本体给外部提供一个克隆体进行使用
3.1.3 工厂模式
对象的使用工厂来创建。
工厂模式(Factory Pattern)提供了一种创建对象的最佳方式。我们不必关心对象的创建细节,只需要根据不同情况获取不同产品即可
3.1.3.1 简单工厂模式
1、工厂的抽象产品
/**
* 工厂的产品
*/
public abstract class AbstractCar {
String engine;
public abstract void run();
}
2、要造的最终产品
public class MiniCar extends AbstractCar{
public MiniCar(){
this.engine = "四缸水平对置发动机";
}
@Override
public void run() {
System.out.println(engine+"--> 嘟嘟嘟...");
}
}
/**
* 具体产品
*/
public class VanCar extends AbstractCar{
public VanCar(){
this.engine = "单杠柴油机";
}
@Override
public void run() {
System.out.println(engine+"--》嗒嗒嗒....");
}
}
3、使用工场创建
/**
* 简单工厂
* 1、产品数量极少
*/
public class WuLinSimpleFactory {
public AbstractCar newCar(String type){
//核心方法:一切从简
if("van".equals(type)){
return new VanCar();
}else if("mini".equals(type)){
return new MiniCar();
}
//.....
//更多的产品,违反开闭原则。应该直接扩展出一个类来造
return null;
}
}
public class MainTest {
public static void main(String[] args) {
WuLinSimpleFactory factory = new WuLinSimpleFactory();
AbstractCar van = factory.newCar("van");
AbstractCar mini = factory.newCar("mini");
AbstractCar zz = factory.newCar("zz");
van.run();
mini.run();
}
}
3.1.3.2 工厂方法模式
简单工厂模式违反开闭原则,新加一个则需要修改工厂类。那么可以把工厂进行抽象。
1、要造的抽象产品
/**
* 工厂的产品
*
* 怎么把一个功能提升一个层次:定义抽象(抽象类,接口)
* 抽象类,接口 就会有多实现,多实现自然就有多功能
*/
public abstract class AbstractCar {
String engine;
public abstract void run();
}
2、具体产品
public class MiniCar extends AbstractCar {
public MiniCar(){
this.engine = "四缸水平对置发动机";
}
@Override
public void run() {
System.out.println(engine+"--> 嘟嘟嘟...");
}
}
/**
* 具体产品
*/
public class VanCar extends AbstractCar {
public VanCar(){
this.engine = "单杠柴油机";
}
@Override
public void run() {
System.out.println(engine+"--》嗒嗒嗒....");
}
}
3、工厂
/**
* 抽象工厂的层级
*/
public abstract class AbstractCarFactory {
public abstract AbstractCar newCar();
}
/**
* minicar分厂
*/
public class WulinMinCarFactory extends AbstractCarFactory{
@Override
public AbstractCar newCar() {
return new MiniCar();
}
}
public class WulinVanCarFactory extends AbstractCarFactory {
@Override
public AbstractCar newCar() {
return new VanCar();
}
}
4、测试
直接扩展抽象工厂类即可。但是产品单一,因此可以再把AbstractCarFactory上一层进行抽象。
public class MainTest {
public static void main(String[] args) {
AbstractCarFactory carFactory = new WulinMinCarFactory();
AbstractCar abstractCar = carFactory.newCar();
abstractCar.run();
carFactory = new WulinVanCarFactory();
AbstractCar abstractCar1 = carFactory.newCar();
abstractCar1.run();
}
}
3.1.3.3 抽象工厂
1、造的产品
产品1
/**
* 工厂的产品
*
* 怎么把一个功能提升一个层次:定义抽象(抽象类,接口)
* 抽象类,接口 就会有多实现,多实现自然就有多功能
*/
public abstract class AbstractCar {
String engine;
public abstract void run();
}
/**
* 具体产品
*/
public class VanCar extends AbstractCar {
public VanCar(){
this.engine = "单杠柴油机";
}
@Override
public void run() {
System.out.println(engine+"--》嗒嗒嗒....");
}
}
public class RacingCar extends AbstractCar {
public RacingCar(){
this.engine = "v8发动机";
}
@Override
public void run() {
System.out.println(engine+"=--嗖.....");
}
}
产品2
/**
* 抽象产品
*/
public abstract class AbstractMask {
Integer price;
public abstract void protectedMe();
}
public class N95Mask extends AbstractMask{
public N95Mask(){
this.price = 2;
}
@Override
public void protectedMe() {
System.out.println("N95口罩....超级防护");
}
}
public class CommonMask extends AbstractMask{
public CommonMask(){
price = 1;
}
@Override
public void protectedMe() {
System.out.println("普通口罩....简单保护...请及时更换");
}
}
2、工厂
集团总厂,定义可以建造的对象种类。可以造车造口罩
* 总厂规范:
* Wulin集团
*
* 使用接口;
*/
public abstract class WulinFactory {
abstract AbstractCar newCar();
abstract AbstractMask newMask();
}
车总厂
/**
* wulin 汽车集团
*/
public abstract class WulinCarFactory extends WulinFactory{
@Override
abstract AbstractCar newCar();
// 不要子类实现
@Override
AbstractMask newMask() {
return null;
}
}
口罩总厂
/**
* wulin口罩集团
*/
public abstract class WulinMaskFactory extends WulinFactory{
@Override
AbstractCar newCar() {
return null;
}
abstract AbstractMask newMask();
}
具体的厂1
/**
* 普通口罩
*/
public class WulinHangZhouMaskFactory extends WulinMaskFactory {
@Override
AbstractMask newMask() {
return new CommonMask();
}
}
/**
* 分厂:N95口罩
*/
public class WulinWuHanMaskFactory extends WulinMaskFactory{
@Override
AbstractMask newMask() {
return new N95Mask();
}
}
具体的产2
public class WulinVanCarFactory extends WulinCarFactory{
@Override
AbstractCar newCar() {
return new VanCar();
}
}
public class WulinRacingCarFactory extends WulinCarFactory {
@Override
AbstractCar newCar() {
return new RacingCar();
}
}
3、测试
/**
* 抽象出来。
* 可以抽象成接口(只有方法),可以抽象成抽象类(有些属性也需要用)
*/
public class MainTest {
public static void main(String[] args) {
WulinFactory wulinFactory = new WulinWuHanMaskFactory();
AbstractMask abstractMask = wulinFactory.newMask();
abstractMask.protectedMe();
wulinFactory = new WulinHangZhouMaskFactory();
AbstractMask abstractMask1 = wulinFactory.newMask();
abstractMask1.protectedMe();
}
}