前提:javaSE
设计模式:要求很好的可扩展性、可维护性、可重用性。高内聚低耦合。
概念 设计模式的七种设计原则 创建型模式(单例模式、工厂模式、原型模式等) 结构型模式(适配器模式、装饰模式、组合模式、外观模式等) 行为型模式(观察者模式、解释器模式、迭代器模式、命令模式等)共 23 种设计模式。
# 概念
## 一、设计模式的重要性:
在软件开发中,设计模式是对软件设计中普遍存在(反复出现)的各种问题所提出的解决方案。
在项目开发过程中,客户会提出新增功能或修改功能的要求。
开发项目的员工离职,需要另一个员工维护该员工的项目。(可读性、规范性)
## 二、学习设计模式的目的:
1、可扩展性。新增功能很方便。
2、可维护性。阅读代码、修改代码很方便。
3、可重用性。相同的代码尽可能保持一份。
4、代码呈现高内聚,低耦合的特性。
## 三、UML图:(重点)
UML:Unified Modeling Language 统一建模语言。
UML图描述类和接口的结构,以及类与类、类与接口、接口与接口之间的关系。
例子:
class Person{
public int id;
protected String name;
private char sex;
float score;
public void add(int a, int b){}
}
interface USB{
int WIDTH = 10;
int HEIGHT = 10;
void sendData();
void recieveData();
}
作业:绘制类和接口的UML图,根据UML图编写对应的java程序。
UML图描述类与类之间的关系:
**代码 uml**
**依赖关系: 类中方法参数是类类型 虚线箭头,箭头指向形参类型**
**继承关系(泛化关系):子类 extends 父类 实线空心箭头,箭头指向父类**
**继承关系是 “是”的关系**
**实现关系: 类 implements 接口 虚线空心箭头,箭头指向接口**
**实现关系是 “能”的关系**
**聚合关系: 类中的成员变量是类类型, 实线空心菱形,菱形指向拥有该类的类**
**可以使用另一个对象初始化**
**组合关系: 类中的成员变量是类类型, 实线实心菱形,菱形指向拥有该类的类**
**通过new对象进行初始化**
**聚合关系 和 组合关系 是 “有”的关系**
作业:
1、抄写类与类之间的关系。
2、画出氧气、动物、鸟、翅膀、大雁、飞翔、雁群之间的关系。
## 四、设计模式的七种设计原则:(重点)
提出实际需求----传统思路解决问题----存在问题----引出设计模式----原理分析-----UML图----使用某种设计模式解决问题
### 1、七种设计原则:
1.1、单一职责原则
1.2、依赖倒置原则
1.3、接口隔离原则:
1.4、里氏替换原则:
1.5、开闭原则:
1.6、迪米特法则:
1.7、合成复用原则:
### 2、单一职责原则:
一个类只负责一个职责。降低类的复杂度。
例子:
定义类实现空中、陆地、水中交通工具的移动功能。
扩展功能:增加太空交通工具移动功能;
修改功能:修改水中交通工具的移动功能。
解决方案:定义空中交通工具类、陆地交通工具类、水中交通工具类。
### 3、依赖倒置原则:
依赖倒置的中心思想是面向接口编程。
使用接口或抽象类的目的是指定好功能和规范,而不设计任何具体的操作,把展现细节的任务交给他们的实现类去完成。
例子:
微信:发送数据的功能。
人:接收数据的功能。接收微信对象发送的数据,并打印数据。
扩展功能:增加QQ、电话
解决方法:定义发送数据接口,微信、QQ、电话实现该接口,人的接收数据方法的参数为接口类型。
### 4、接口隔离原则:
将一个接口拆分成多个接口,不同的类与他们所需要的接口建立依赖关系。
例子:
出租车公司--work()、游艇公司--work()、航空公司--work()、白宫--work() 、一个接口
传统:
```
interface Power{
public void car();
public void ship();
public void plane();
}
//创建人
class CarPerson implements Power{
@Override
public void car() {
System.out.println("我会开车");
}
@Override
public void ship() {}
@Override
public void plane() {}
}
class ShipPerson implements Power{
@Override
public void car() {}
@Override
public void ship() {
System.out.println("我会开船");
}
@Override
public void plane() {}
}
class PlanePerson implements Power{
@Override
public void car() {}
@Override
public void ship() {}
@Override
public void plane() {
System.out.println("我会开飞机");
}
}
class BaobiaoPerson implements Power{
@Override
public void car() {
System.out.println("我会开车");
}
@Override
public void ship() {
System.out.println("我会开船");
}
@Override
public void plane() {
System.out.println("我会开飞机");
}
}
//创建公司
class CarCompant{
public void work(Power power){
power.car();
System.out.println("这个人会开车,出租车公司正常运营");
}
}
class ShipCompant{
public void work(Power power){
power.ship();
System.out.println("这个人会开船,船务公司公司正常运营");
}
}
class PlaneCompant{
public void work(Power power){
power.plane();
System.out.println("这个人会开飞机,航空公司正常运营");
}
}
class BaobiaorCompant{
public void work(Power power){
power.car();
power.ship();
power.plane();
System.out.println("这个人会开车、快船、开飞机,保镖公司公司正常运营");
}
}
public class MyTest {
public static void main(String[] args) {
//创建公司
CarCompant carCompant = new CarCompant();
ShipCompant shipCompant = new ShipCompant();
PlaneCompant planeCompant = new PlaneCompant();
BaobiaorCompant baobiaorCompant = new BaobiaorCompant();
//创建人
CarPerson carPerson = new CarPerson();
ShipPerson shipPerson = new ShipPerson();
PlanePerson planePerson = new PlanePerson();
BaobiaoPerson baobiaoPerson = new BaobiaoPerson();
//公司运转
carCompant.work(carPerson);
shipCompant.work(shipPerson);
planeCompant.work(planePerson);
baobiaorCompant.work(baobiaoPerson);
}
}
```
接口隔离原则:
```
//创建接口
interface CarPower{
public void car();
}
interface ShipPower{
public void ship();
}
interface PlanePower{
public void plane();
}
interface AllPower extends CarPower, ShipPower, PlanePower{
}
//创建人
class CarPerson implements CarPower {
@Override
public void car() {
System.out.println("我会开车");
}
}
class ShipPerson implements ShipPower{
@Override
public void ship() {
System.out.println("我会开船");
}
}
class PlanePerson implements PlanePower{
@Override
public void plane() {
System.out.println("我会开飞机");
}
}
class BaobiaoPerson implements AllPower{
@Override
public void car() {
System.out.println("我会开车");
}
@Override
public void ship() {
System.out.println("我会开船");
}
@Override
public void plane() {
System.out.println("我会开飞机");
}
}
//创建公司
class CarCompant{
public void work(CarPower power){
power.car();
System.out.println("这个人会开车,出租车公司正常运营");
}
}
class ShipCompant{
public void work(ShipPower power){
power.ship();
System.out.println("这个人会开船,船务公司公司正常运营");
}
}
class PlaneCompant{
public void work(PlanePower power){
power.plane();
System.out.println("这个人会开飞机,航空公司正常运营");
}
}
class BaobiaorCompant{
public void work(AllPower power){
power.car();
power.ship();
power.plane();
System.out.println("这个人会开车、快船、开飞机,保镖公司公司正常运营");
}
}
public class MyTest {
public static void main(String[] args) {
//创建公司
CarCompant carCompant = new CarCompant();
ShipCompant shipCompant = new ShipCompant();
PlaneCompant planeCompant = new PlaneCompant();
BaobiaorCompant baobiaorCompant = new BaobiaorCompant();
//创建人
CarPerson carPerson = new CarPerson();
ShipPerson shipPerson = new ShipPerson();
PlanePerson planePerson = new PlanePerson();
BaobiaoPerson baobiaoPerson = new BaobiaoPerson();
//公司运转
carCompant.work(carPerson);
shipCompant.work(shipPerson);
planeCompant.work(planePerson);
baobiaorCompant.work(baobiaoPerson);
}
}
```
### 5、里氏替换原则:
在使用继承的时候,在子类中尽量不要重写父类中的方法。
以便做的 所有引用父类的地方必须能够透明的使用其子类对象。
在适当的情况下,通过提取接口或抽象类、聚合、组合的方法解决问题。
例子:
一个A类,计算加法,计算乘法;另一个B类继承A类,对A中计算加法的方法重写。
传统:
```
class A{
public int count(int a, int b){
return a + b;
}
public int factor(int a){
int total = 1;
for (int i=2; i<=a; i++){
total *= i;
}
return total;
}
}
class B extends A{
public int count(int a, int b){
return a - b;
}
}
public class MyTest {
static void f(A oa){
int i = oa.count(3, 4);
System.out.println("3+4=" + i);
}
public static void main(String[] args) {
A oa = new A();
B ob = new B();
f(oa);
f(ob);
}
}
```
里氏替换:
```
interface Count{
public int count(int a, int b);
}
class A implements Count{
public int count(int a, int b){
return a + b;
}
public int factor(int a){
int total = 1;
for (int i=2; i<=a; i++){
total *= i;
}
return total;
}
}
class B implements Count{
public int count(int a, int b){
return a - b;
}
A oa = new A();
}
public class MyTest {
static void f(A oa){
int i = oa.count(3, 4);
System.out.println("3+4=" + i);
}
public static void main(String[] args) {
A oa = new A();
B ob = new B();
f(oa);
//f(ob)
int a = ob.oa.factor(5);
System.out.println(a);
}
}
```
### 6、开闭原则:
模块和函数应该对扩展开发,对修改关闭,用抽象构建框架,用实现扩展细节。
当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
编程中遵循其他原则,以及使用设计模式的目的就是遵循开闭原则。
问题:打印形状。打印圆形、方形、矩形。扩展:打印三角形。
传统:
```
class ShapeOper{
public void printShape(int sort){
switch (sort){
case 1:
System.out.println("打印圆形");
break;
case 2:
System.out.println("打印方形");
break;
case 3:
System.out.println("打印矩形");
break;
case 4:
System.out.println("打印三角形");
break;
}
}
}
public class MyTest {
public static void main(String[] args) {
ShapeOper shapeOper = new ShapeOper();
shapeOper.printShape(1);
shapeOper.printShape(2);
shapeOper.printShape(3);
}
}
```
开闭原则:
```
interface PrintShape {
public void draw();
}
class 圆形 implements PrintShape{
public void draw() {
System.out.println("画了一个圆形");
}
}
class 矩形 implements PrintShape{
public void draw() {
System.out.println("画了一个矩形");
}
}
class 方形 implements PrintShape{
public void draw() {
System.out.println("画了一个方形");
}
}
class ShapeOper{
public void print(PrintShape printShape){
printShape.draw();
}
}
public class 三角形 implements PrintShape{
@Override
public void draw() {
System.out.println("打印三角形");
}
}
public class MyTest {
public static void main(String[] args) {
ShapeOper shapeOper = new ShapeOper();
圆形 yuan = new 圆形();
方形 fang = new 方形();
矩形 ju = new 矩形();
三角形 san = new 三角形();
shapeOper.print(yuan);
shapeOper.print(fang);
shapeOper.print(ju);
shapeOper.print(san);
}
}
```
### 7、迪米特法则:
又称为最少知道原则,即一个类对自己依赖的类知道的越少越好。
对于被依赖的类不管多么复杂,都尽量将逻辑处理封装在类的内部,对外提供public方法,不对外泄露任何信息。
直接朋友:类中出现在成员变量、方法参数、方法返回类型中的类是直接朋友。
如:class A{
D od;
B f(C oc){}
}
陌生朋友:类中的方法中的局部变量的类是陌生朋友。
如:class A{
void f(){
B ob = new B();
}
}
问题:
学生类 班级类 聚合关系
打印类 打印班级信息,以及班级中的学生信息。
传统:
```
class Student{
private int id;
private String name;
private int age;
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Grade{
private int id;
private String name;
List
public Grade(int id, String name, List
this.id = id;
this.name = name;
this.list = list;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;