设计模式七大原则
第一章
设计模式的目的
设计模式的七大原则(要有印象)
1.开闭原则:用抽象构建架构,用实现扩展细节
2.依赖倒置原则:高层模块不应该依赖于底层模块,二者都应该依赖其抽象
3.单一职责原则:单个接口或类不应该有多个职责,应该尽可能的划分职责,通过组合的方式,完成更为复杂的业务
4.接口隔离原则:一个接口不要包含过多的职责,应合理划分,跟单一职责原则相辅相成
典型场景:动物、人、鸟,人和鸟都会吃,人会走路,鸟会飞,应该把走路和飞这两个行为抽象成接口,通过组合的方式让人拥有走路的行为,让鸟拥有飞的行为。再细划分,人有多个走路姿势,鸟有多个飞行方式,可以分别继承走路和飞的抽象行为扩展其具体的行为
5.迪米特法则:也就最少知道原则,一个对象尽量让其它对象保持最少的了解
典型场景:我点外卖,我只关心外卖员,不关系具体的店。我的类中只依赖外卖员,不会依赖具体的店。是不是静态代理。
6.里氏替换原则:在引用父类的地方,都可以替换为其子类。从而可以实现子类间的动态切换。换句话说就是要有面向接口的编程思维。结合“开闭原则”,完美
7.合成复用原则:多用组合,少用继承
单一职责原则
解释:
在面对对象编程中,每个对象只负责自己的任务,比如该提供数据的就只是提供数据,该负责提供服务的就只提供服务,或者只是维护对象之间的关系,这样的开发方式代码耦合度较低,较灵活,易扩展。
https://blog.csdn.net/zhengzhb/article/details/7278174
接口隔离原则
基本介绍
一个类通过接口去依赖另一个类,依赖应该建立在最小的接口下
https://blog.csdn.net/king123456man/article/details/81626059
https://www.cnblogs.com/alunchen/p/7115675.html
例子
/**
* @Author: suny
* @Date: 2021/11/04 下午6:56
* @Description:
*/
public class Segregation1 {
public static void main(String[] args) {
}
}
//接口 默认权限的修饰符是public
interface Interface1 {
void operation1();
void operation2();
void operation3();
void operation4();
void operation5();
}
//类B
class B implements Interface1 {
@Override
public void operation1() {
System.out.println("B实习了操作1");
}
@Override
public void operation2() {
System.out.println("B实习了操作2");
}
@Override
public void operation3() {
System.out.println("B实习了操作3");
}
@Override
public void operation4() {
System.out.println("B实习了操作4");
}
@Override
public void operation5() {
System.out.println("B实习了操作5");
}
}
//类D
class D implements Interface1 {
@Override
public void operation1() {
System.out.println("B实习了操作1");
}
@Override
public void operation2() {
System.out.println("B实习了操作2");
}
@Override
public void operation3() {
System.out.println("B实习了操作3");
}
@Override
public void operation4() {
System.out.println("B实习了操作4");
}
@Override
public void operation5() {
System.out.println("B实习了操作5");
}
}
// A类通过接口Interface1 依赖(使用) B类,但是只会用到1,2,3方法
class A {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend2(Interface1 i) {
i.operation2();
}
public void depend3(Interface1 i) {
i.operation3();
}
}
// A类通过接口Interface1 依赖(使用) B类,但是只会用到1,4,5方法
class C {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend2(Interface1 i) {
i.operation4();
}
public void depend3(Interface1 i) {
i.operation5();
}
}
改进
/**
* @Author: suny
* @Date: 2021/11/04 下午6:56
* @Description: 接口隔离原则
*/
public class Segregation1Better {
public static void main(String[] args) throws InterruptedException {
A1 a1 = new A1();
//A1类通过接口去依赖(使用)B1类
a1.depend1(new B1());
a1.depend2(new B1());
a1.depend3(new B1());
System.out.println("****************");
C1 c1 = new C1();
//C1类通过接口去依赖(使用)D类
c1.depend1(new D1());
c1.depend2(new D1());
c1.depend3(new D1());
}
}
//接口 默认权限的修饰符是public
interface Interface01 {
void operation1();
}
interface Interface02 {
void operation2();
void operation3();
}
interface Interface03 {
void operation4();
void operation5();
}
class B1 implements Interface01,Interface02 {
@Override
public void operation1() {
System.out.println("B实习了操作1");
}
@Override
public void operation2() {
System.out.println("B实习了操作2");
}
@Override
public void operation3() {
System.out.println("B实习了操作3");
}
}
class D1 implements Interface01,Interface03 {
@Override
public void operation1() {
System.out.println("D实习了操作1");
}
@Override
public void operation4() {
System.out.println("D实习了操作4");
}
@Override
public void operation5() {
System.out.println("D实习了操作5");
}
}
class A1 {
void depend1(Interface01 i){
i.operation1();
}
void depend2(Interface02 i){
i.operation2();
}
void depend3(Interface02 i){
i.operation3();
}
}
class C1 {
void depend1(Interface01 i){
i.operation1();
}
void depend2(Interface03 i){
i.operation4();
}
void depend3(Interface03 i){
i.operation5();
}
}
依赖倒转原则
https://blog.csdn.net/king123456man/article/details/81626127
https://www.cnblogs.com/rmxd/p/12539269.html
例子
/**
* @Author: suny
* @Date: 2021/11/04 下午8:38
* @Description:
*/
public class DependecyInversion {
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
}
}
class Email {
public String getInfo() {
return "电子邮件信息:hello world!";
}
}
//完成Person接受消息的功能
//方式 1
// 1.简单,容易
// 2 如果我们获取的对象是微信,短信, 增新增类,Person类要增加接受方法
// 3 解决思路: 引入一个抽象的接口 IReveiver,表示接受者,这样Person类和接口发生依赖
// 因为Email,WeiXin 等 都是接受范围,他们各自实习IReveiver接口就可以,这样就实现类符号依赖倒置原则
class Person {
public void receive(Email email) {
System.out.println(email.getInfo());
}
}
改进
package com.inversion;
/**
* @Author: suny
* @Date: 2021/11/04 下午8:38
* @Description:
*/
public class DependecyInversionBetter {
public static void main(String[] args) {
//=客户端不需要改变
Person2 person = new Person2();
person.receive(new Email2());
person.receive(new WeiXin());
}
}
//定义一个接口
interface IReceiver {
public String getInfo();
}
class Email2 implements IReceiver{
public String getInfo() {
return "电子邮件信息:hello world!";
}
}
class WeiXin implements IReceiver{
@Override
public String getInfo() {
return "微信信息:Hi WeiXin!";
}
}
class Person2 {
public void receive(IReceiver receiver) {
System.out.println(receiver.getInfo());
}
}
依赖关系的传递3种:
接口传递依赖、构造方法、setter方法
import jdk.nashorn.internal.runtime.regexp.joni.constants.OPCode;
/**
* @Author: suny
* @Date: 2021/11/04 下午9:18
* @Description: 依赖的传递方式
*/
public class Cdfs {
public static void main(String[] args) {
//接口依赖传递
AppleTV appleTV = new AppleTV();
OpenAndClose openAndClose = new OpenAndClose();
openAndClose.open(appleTV);
//构造器进行依赖传递 常用
OpenAndClose2 openAndClose2 = new OpenAndClose2(new XiaoMiTV());
openAndClose2.open();
//setter方法依赖传递 常用
OpenAndClose3 openAndClose3 = new OpenAndClose3();
openAndClose3.setTv(new HuaWeiTV());
openAndClose3.open();
}
}
// 方式1 通过接口实现依赖传递
//开关的接口
interface IOpenAndCLose {
public void open(ITV tv);
}
// ITV接口
interface ITV {
public void play();
}
class AppleTV implements ITV {
@Override
public void play() {
System.out.println("打开苹果TV");
}
}
//接口的实现
class OpenAndClose implements IOpenAndCLose{
@Override
public void open(ITV tv) {
tv.play();
}
}
//方式2 通过构造方法实现依赖传递
interface IOpenAndCLose2 {
public void open();
}
// ITV接口
interface ITV2 {
public void play();
}
class XiaoMiTV implements ITV2{
@Override
public void play() {
System.out.println("打开小米TV");
}
}
//接口的实现
class OpenAndClose2 implements IOpenAndCLose2{
public ITV2 itv2;
public OpenAndClose2(ITV2 itv2){
this.itv2 = itv2;
}
@Override
public void open() {
itv2.play();
}
}
// 方式3 通过setter方法
interface IOpenAndCLose3 {
public void open();
public void setTv(ITV3 itv3);
}
// ITV接口
interface ITV3 {
public void play();
}
class HuaWeiTV implements ITV3{
@Override
public void play() {
System.out.println("打开华为TV");
}
}
//接口的实现
class OpenAndClose3 implements IOpenAndCLose3{
public ITV3 itv3;
@Override
public void setTv(ITV3 itv3) {
this.itv3 = itv3;
}
@Override
public void open() {
this.itv3.play();
}
}
里氏替换原则
原则:
用子类替换父类,对之前用父类的地方没有影响
子类尽量不要重写父类方法
原来的父类和子类都继承一个更通俗的父类,原有的继承关系去掉,采用依赖,聚合,组合的关系代替。
https://blog.csdn.net/zhengzhb/article/details/7281833
开闭原则
提供者提供修改,使用时关闭修改权限
http://c.biancheng.net/view/1322.html
迪米特法则
最少知道原则
https://blog.csdn.net/qq_38844728/article/details/88739574
合成复用原则
合成复用原则由成为组合/聚合复用原则,尽量使用对象组合,而不是继承来达到复用的目的