尚硅谷设计模式学习---[设计模式七大原则]
Posted 小智RE0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了尚硅谷设计模式学习---[设计模式七大原则]相关的知识,希望对你有一定的参考价值。
尚硅谷传送门==>B站尚硅谷Java设计模式
❤❤❤感谢尚硅谷❤❤❤
最近开始计划学习一下设计模式了,加油!!!
目录
设计模式就是对软件设计中普遍存在(反复出现)的问题,提出的解决方案.
面向对象 = =>功能模块[设计模式+算法(数据结构)]
= =>框架[使用到多种设计模式]= = >架构 [服务器集群]
设计模式的目的是为了 提高代码的可重用性
(相同功能的代码提取出来), 可读性
(编写程序时规范书写),可扩展性
(方便扩展增加新功能), 可靠性
(增加新功能后不影响原来的代码),使得程序高内聚,低耦合.
七大原则是指==> 单一职责原则
; 接口隔离原则
;依赖倒置原则
;里氏替换原则
;开闭原则
;迪米特原则
;合成复用原则
.
尽量针对接口编程
1.单一职责原则( Single Responsibility Principle)
通俗地说就是, 一个类就管理一件事, 职责单一;
比如说一个实体类
User
,它就只负责用户的属性和方法.
或者说在一个类中;每个方法仅负责自己的功能;各司其职;
降低了类的复杂性
;提高了可读性
案例:比如说有个交通工具类Transport
/**
* @Date: 2021/09/21/12:13
* 单一职责原则学习
*/
public class SingleResponsibility01 {
public static void main(String[] args) {
Transport transport = new Transport();
transport.run("小汽车");
transport.run("轮船");
transport.run("飞机");
}
}
//交通工具类
class Transport{
public void run(String transport){
System.out.println(transport+"正在路上跑");
}
}
诶,运行后发现;明显不符合逻辑啊;违反了单一职责的原则.
小汽车正在路上跑
轮船正在路上跑
飞机正在路上跑
OK,接下来对它进行修改;
方式1;把交通工具这个类分解开;分成 路上跑的; 天上飞的; 水里游的 交通工具;
/**
* @Date: 2021/09/21/12:28
* 单一职责原则学习
*/
public class SingleResponsibility02 {
public static void main(String[] args) {
RoundTransport roundTransport = new RoundTransport();
roundTransport.run("小汽车");
SkyTransport skyTransport = new SkyTransport();
skyTransport.run("飞机");
SwimTransport swimTransport = new SwimTransport();
swimTransport.run("轮船");
}
}
//将原来的交通工具类分类;分为3个类;
//路上跑的交通工具类;
class RoundTransport{
public void run(String roundTransport){
System.out.println(roundTransport+"在路上跑");
}
}
//在天上飞的工具;
class SkyTransport{
public void run(String skyTransport){
System.out.println(skyTransport+"在天上飞");
}
}
//在水里游的工具;
class SwimTransport{
public void run(String swimTransport){
System.out.println(swimTransport+"在水里游");
}
}
诶,每个类负责一种交通工具;
小汽车在路上跑
飞机在天上飞
轮船在水里游
虽然说遵守了单一职责原则,但是将原先的类分解,同时修改了客户端;
方式2;直接在交通工具类中扩展不同的方法;分别负责不同的功能;
public class SingleResponsibility03 {
public static void main(String[] args) {
Transport transport = new Transport();
transport.runRond("小汽车");
transport.runSwim("轮船");
transport.runSky("飞机");
}
}
//交通工具类
class Transport{
//路上跑的交通工具执行方法;
public void runRond(String transport){
System.out.println(transport+"正在路上跑");
}
//天上飞的交通工具执行方法;
public void runSky(String transport){
System.out.println(transport+"正在天上飞");
}
//水里游的交通工具执行方法;
public void runSwim(String transport){
System.out.println(transport+"正在水里游");
}
}
每个方法负责实现一种功能;在方法上,遵守了单一职责原则
小汽车正在路上跑
轮船正在水里游
飞机正在天上飞
2.接口隔离原则(Interface Segregation Principle)
比如说,一个接口有许多方法,但是类 A 需要的功能只有几个方法,那么就需要把原来的接口拆分一下,让类A去通过他需要的接口去使用方法.
案例;
一个接口有5个方法;类B和类D实现接口;
而类A依赖类B后,仅使用方法1,方法2,方法3;
而类C依赖类D后;仅使用方法1,方法4,方法5;
package com.lzq.principle.interfacesegregation;
public class InterfaceSegregation01 {
public static void main(String[] args) {
}
}
//接口'
interface Interface1{
void method1();
void method2();
void method3();
void method4();
void method5();
}
//类 B 实现接口;
class B implements Interface1{
public void method1() {
System.out.println("类B实现接口的方法1 ");
}
public void method2() {
System.out.println("类B实现接口的方法2 ");
}
public void method3() {
System.out.println("类B实现接口的方法3 ");
}
public void method4() {
System.out.println("类B实现接口的方法4 ");
}
public void method5() {
System.out.println("类B实现接口的方法5 ");
}
}
//类 D 实现接口;
class D implements Interface1{
public void method1() {
System.out.println("类D实现接口的方法1 ");
}
public void method2() {
System.out.println("类D实现接口的方法2 ");
}
public void method3() {
System.out.println("类D实现接口的方法3 ");
}
public void method4() {
System.out.println("类D实现接口的方法4 ");
}
public void method5() {
System.out.println("类D实现接口的方法5 ");
}
}
//类 A 通过参数接口 依赖 类B ; 仅需要方法1,方法2,方法3;
class A{
public void depend1(Interface1 interface1){
interface1.method1();
}
public void depend2(Interface1 interface1){
interface1.method2();
}
public void depend3(Interface1 interface1){
interface1.method3();
}
}
//类 C 通过参数接口 依赖 类D ,仅需要方法1,方法4,方法5;
class C{
public void depend1(Interface1 interface1){
interface1.method1();
}
public void depend4(Interface1 interface1){
interface1.method4();
}
public void depend5(Interface1 interface1){
interface1.method5();
}
}
但是,按着这样分配的话,那么类C没必要去写方法4和方法5;类D没有必要去写方法2和方法3;
优化
将接口拆分为3个接口;
一个接口放置方法1;
一个接口放置方法2和方法3;
一个接口放置方法4和方法5.
package com.lzq.principle.interfacesegregation;
/**
* @Date: 2021/09/21/13:00
*/
public class InterfaceSegregation02 {
public static void main(String[] args) {
//类A通过接口去使用类B;
A a=new A();
a.depend1(new B());
a.depend2(new B());
a.depend3(new B());
//类C通过接口去使用类D;
C c=new C();
c.depend1(new D());
c.depend4(new D());
c.depend5(new D());
}
}
//接口'
interface Interface1{
void method1();
}
//接口拆分出的接口2;
interface Interface2{
void method2();
void method3();
}
//接口拆分出的接口3;
interface Interface3{
void method4();
void method5();
}
//类 B 实现接口;
class B implements Interface1,Interface2{
public void method1() {
System.out.println("类B实现接口1的方法1 ");
}
public void method2() {
System.out.println("类B实现接口2的方法2 ");
}
public void method3() {
System.out.println("类B实现接口2的方法3 ");
}
}
//类 D 实现接口;
class D implements Interface1,Interface3{
public void method1() {
System.out.println("类D实现接口1的方法1 ");
}
public void method4() {
System.out.println("类D实现接口3的方法4 ");
}
public void method5() {
System.out.println("类D实现接口3的方法5 ");
}
}
//类 A 通过参数接口 依赖 类B ; 仅需要方法1,方法2,方法3;
class A{
public void depend1(Interface1 interface1){
interface1.method1();
}
public void depend2(Interface2 interface2){
interface2.method2();
}
public void depend3(Interface2 interface2){
interface2.method3();
}
}
//类 C 通过参数接口 依赖 类D ,仅需要方法1,方法4,方法5;
class C{
public void depend1(Interface1 interface1){
interface1.method1();
}
public void depend4(Interface3 interface3){
interface3.method4();
}
public void depend5(Interface3 interface3){
interface3.method5();
}
}
输出
类B实现接口1的方法1
类B实现接口2的方法2
类B实现接口2的方法3
类D实现接口1的方法1
类D实现接口3的方法4
类D实现接口3的方法5
3.依赖倒置原则(Dependence Inversion Principle)
核心就是面向接口编程;
让细节的具体实现类去依赖(使用)抽象类或者接口;而不是让接口或抽象类去依赖细节的具体实现类.
案例;
不用依赖倒置原则的案例;
比如说,有一个短信类,一个QQ消息类;
在用户Person类中需要不同的方法接受不同的消息.
public class DependenceInversion01 {
public static void main(String[] args) {
Person person=new Person();
person.getMes(new QQ());
person.getMes(new Message());
}
}
//短信类;
class Message{
public String show(){
return "收到短信了";
}
}
//QQ消息;
class QQ{
public String show(){
return "收到QQ消息了";
}
}
//具体的人;
class Person{
//接收短信;
public void getMes(Message message){
System.out.println(message.show());
}
//接收QQ消息;
public void getMes(QQ qq){
System.out.println(qq.show());
}
}
虽然输出没什么问题;但是一旦又需要接受电子邮件信息呢,接受电话呢…;又要在Person类中重新写方法吗?
收到QQ消息了
收到短信了
根据依赖倒置原则进行案例优化
将接受消息的方法提取;变为接口GetMes;
这样,即使需要接受别的消息,也不用在Person类中再去增加方法;
public class DependenceInversion02 {
public static void main(String[] args) {
Person person=new Person();
person.getMes(new QQ());
person.getMes(new Message());
}
}
//接收消息的接口;
interface GetMes{
//看看收到的消息;
String show();
}
//短信类;
class Message implements GetMes{
public String show(){
return "收到短信了";
}
}
//QQ消息;
class QQ implements GetMes{
public String show(){
return "收到QQ消息了";
}
}
//具体的人;
class Person{
//接收消息;
public void getMes(GetMes getMes){
System.out.println(getMes.show());
}
}
关于依赖倒置原则中的依赖关系传递三种方式;
接口传递
;构造方法传递
;setter方法传递
4.里氏替换原则(Liskov Substitution Principle)
在面向对象编程语言的继承关系中,父类已经实现的方法,若子类进行修改,可能会产生问题.
使用继承虽然是比较方便的,但是会出现入侵,程序的可移植性降低,程序间的耦合性过高.
根据里氏替换原则,子类中尽量不要重写父类的方法;
所有引用父类的位置,要做到可以透明地使用子类的对象.
如果说子类还是需要父类的方法,可采用聚合,组合,依赖的方式.
案例;类 B 继承了类 A后,没有注意到已经重写了类A的方法 func1();
而且在重写的方法内修改了具体实现.
public class LiskovSubstitution01 {
public static void main(String[] args) {
System.out.println("类A调用方法");
A a = new A();
System.out.println("11-3=" + a.func1(11, 3));
System.out.println("1-8=" + a.func1(1, 8));
System.out.println("类B调用方法");
B b = new B();
System.out.println("11-3=" + b.func1(11, 3));
System.out.println("1-8=" + b.func1(1, 8));
System.out.println("11+3+9=" + b.func2(11, 3));
}
}
//类 A 完成两数相减的任务;
class A {
public int func1(int num1, int num2) 尚硅谷设计模式学习(16)---[访问者模式(Visitor Pattern)]