Java:一篇学好设计模式_世界热点评

2023-04-13 11:25:10 来源:博客园
什么是设计模式

简单理解,设计模式是前人多年写代码踩坑总结出来的优秀代码攻略,目的是减少大量无用代码,让项目更好维护

七大设计原则

接下来要讲的23种设计模式,但遵循下面的七大原则:

单一职责原则2、接口隔离原则依赖倒置原则4、里氏替换原则开闭原则迪米特原则合成复用原则
单一职责原则

单一职责原则,目的是每个类履行一种职责。好比一个人是医生,就好好干医生份内事,无需插手护士、保洁等和医生职责无关事


(资料图)

反例

比如说一个Person类,有工作work的方法:

public class Person{public void work(String person){System.out.println("职位为:"+ person + "的人正在工作");}}

这个Person,根据传的person能做各种职位的事,破坏了单一职责

正例
public interface Person{public void work();}
public class Doctor implement Person{public void work(){}}public class Teacher implement Person{public void work(){}}
接口隔离原则

这个原则有点难讲,总结就是把接口拆成最简。

反例

有一个Person,有 fight打人、eat吃饭、work工作三个方法

public interface Person{public void fight();public void eat();public void work();}

现在有两个类:PersonA 和 PersonB 都实现了Person接口,实际上PersonA根本不需要打人,PersonB不需要工作。

正例
public interface Person1{public void eat();}public interface Person2 extend Person1{public void fight();}public interface Person3 extend Person1{public void work();}

拆成3个接口。如此一来,PersonA只需要实现Person3,PersonAB实现Person2

依赖倒置原则

依赖倒置原则,核心在于面向接口编程,传细节,定抽象。

反例

有个Person类,有send方法。

public class Person{public void send(Email mail){System.out.println(mail.getInfo());}}

这方法只能发邮件,那我发短信啥的就不行了

正例

定义3个接口

public interface Receiver{public void getInfo();}public class Email implement Receiver{public void getInfo(){}}public class WeiXin  implement Receiver{public void getInfo(){}}

结果:

public class Person{public void send(Receiver r){System.out.println(mail.getInfo());}}
里氏替换原则

里氏替换原则,他的核心在于:尽量子类不用去重写父类的方法。

开闭原则

开闭原则,核心在于:对外允许拓展,对内拒绝修改。什么意思呢?比如现在我给你了空的羽毛球圆筒,对外只需要装合适的羽毛球即可,对内是不拒绝像把羽毛球筒硬搞成方的

再举个例子,一些配置文件有些参数是固定好的,比如 server.port。对内可以编写自己的参数,对内是不允许修改server.port的参数名

迪米特原则

迪米特原则,被依赖的类尽量让依赖类知道的内部实现细节尽量少,总结就是降低耦合

合成复用原则

合成复用原则,当使用另一个类的方法时,尽量使用聚合的方式,减少使用继承。

这个比较好理解,现在有A类有个A1方法,B想要使用A1。不好的做法就是B去继承A,然后就有A1方法。推荐是B里引入A,然后调用A去用A1

设计模式

设计模式可分为3种类型,下面列举需要重点掌握的设计模式

创建型模式:单例模式,工厂模式,原型模式,建造者模式结构型模式:适配器模式,装饰模式,代理模式行为型模式:观察者模式

单例模式

单例模式,要求在整个应用中一个类只有一个对象实例。刚开始此模式,懒汉和饿汉式的单例代码比较经典,大家有空去看下。

然后在spring最常见的单例就是我们的组件,默认都是单例的,也是单例的体现。

工厂模式简单工厂模式

比如车有很多品牌:奥迪、宝马、保时捷...如果我要一辆宝马,那我得手动new,要一辆保时捷还是得new。那简单工厂模式,在这里可以定义一个创建车工厂类,传入参数拿到不同品牌车。如:

Car car = CarFactory.getCar(String brand);
抽象工厂模式

抽象工厂模式是简单工厂模式的升级版。简单工厂模式从一个工厂拿不同牌子的车,那如果某个牌子中细分有车型,颜色....那单个工厂显然不够用了

利用抽象工厂模式,可以从工厂方法A中拿到某个牌子的工厂B,再根据B拿到具体的车,如下:

BrandCarFactory brandCarFactory = CarFactory.getBrandCarFactory(String brand);Car car = brandCarFactory.getCar(String color,String size....)
原型模式

原型模式,通过原型对象构建出和他属性一样的实例。比如说创建10只羊,每次羊都叫喜羊羊,18岁。当第一只创建后,第二只的创建属性都从第一支获取

spring的bean配置为多例时,利用到的就是原型模式。

建造者模式

建造者模式,和工厂模式有点类似。说起来有点难讲,还是看下例子:

执行入口:
public class Demo{public static void main(String[] args) {        HouseDiretor dir = new HouseDiretor(new HightHouse());House house = dir.buildHouse();    }}
各个类:
//房子构造者public abstract class HouseBuilder{private House house = new House();public void buildA();public void buildB();public void buildC();public void buildHouse(){return house;}}//高楼public class HightHouse extends HouseBuilder{public void buildA(){...}public void buildB(){...}public void buildC(){....}}//指挥者public class HouseDiretor{private HouseBuilder builder;public HouseDiretor(HouseBuilder builder){this.builder = builder;}public void buildHouse(){builder.buildA();builder.buildB();builder.buildC();return builder.buildHouse();}}
适配器模式

适配器模式,就很好理解了。平时大家见过的转接头就是适配器,比如你笔记本只有USB接口,但插口是HIDM,这就需要一个HIDM转USB的转换器充当连接。

类适配器模式

下面以充电器将220V转5V电压作为适配器来编写例子:5V接口:

public interface Inter5V{public int output5V();}

220V实现类

public class Impl220V {public int output220V(){return 220;}}

适配器类

public class Impl5V extends Impl220V implement Inter5V{public int output5V(){return output220V()/24}}

比如现在手机要充电

public class Phone{public void charging(Inter5V inter5V){if(inter5V.output5V == 5){ //可以充电了}else{//不能充电}}}    public static void main(String[] args) {        Phone phone = new Phone();phone.charging(new Impl55V)    }
对象适配器模式

类适配器模式在于继承,这种方式有局限性。而对象适配器模式在于聚合,没有继承关系限制。还是按上面的例子,但是某些类发生变化:适配器类

public class Impl5V implement Inter5V{private Impl220V impl220V;;public Impl20V(Impl220V impl220V){this.impl220V = impl220V;}public int output5V(){return impl220V.output220V()/24}}

充电入口:

public static void main(String[] args) {        Phone phone = new Phone();phone.charging(new Impl55V(new Impl220V())) }
接口适配器模式

接口适配器模式,和上面两种不太一样。他解决是这样一个问题:接口的方法不想全部实现,只实现自己要用的即可

接口适配器往往会定义抽一个抽象类,去实现A接口的所有方法,但是方法体全为空。然后我们再去继承抽象类,选择性重写自己的方法即可。

装饰者模式

装饰者模式,在于解决银排列组合问题。就比如说牛肉面,排骨面...这些都是固定死的,理想状态是一碗面,想加啥自己加。在Java在装饰罩的体现,有个很重要的前提,就是被装饰着和装饰者都会实现或继承相同的父类,具体参考如下:https://blog.csdn.net/m0_47944994/article/details/127901010

装饰者A a = new 装饰者A(new 被装饰者)装饰者B b = new 装饰者B(new 被装饰者)

代理模式

代理模式,在不改动A方法的基础上,代理类(增强类)对A方法进行前后的增强。

代理模式可以分为三种:静态代理,动态代理(JDK代理,接口代理),cglib代理

静态代理

静态代理,有个重要的前提是:代理类和被代理类都要实现同一接口,直接上例子:同一接口:

public interface ITeateacher{public void teach();}

被代理类:

public class Teacher implments ITeateacher{public void teach(){System.out.println("教学生");}}

代理类:

public class TeacherProxy implments ITeateacher{public ITeateacher teacher;public TeacherProxy(ITeateacher teacher){this.teacher = teacher;}public void teach(){System.out.println("备课");teacher.teacher();System.out.println("下课");}}

使用:

public static void main(String[] args) {ITeateacher teacher = new TeacherProxy(nwe Teacher());teacher.teach()}

好处就不说了,就是方法增强了。但缺点是实现同一接口,后面接口方法进行拓展不好维护

动态代理

动态代理也被叫JDK代理,因为代理对象是依赖JDK的API来生成的,不需要我们去创建代理类。

前提要求是目标类是要实现接口的,并且是对接口的所有方法进行增强,实例如下:

目标类接口:

public interface ITeacherDao {    public String teach(String person);}

目标类:

public class TeacherDao implements ITeacherDao{    @Override    public String teach(String person) {        return person + "在教书";    }}

代理工厂类,我们编写用于获取代理对象:

public class ProxyFactory {public ProxyFactory(Object targetObj){        this.targetObj = targetObj;    }public Object getProxyIntance(){        return Proxy.newProxyInstance(targetObj.getClass().getClassLoader(), targetObj.getClass().getInterfaces()                , new InvocationHandler() {                    @Override                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                        System.out.println("增强前代码");                        Object returnValue = method.invoke(targetObj, args);                        System.out.println(returnValue);                        System.out.println("增强后代码");                        return returnValue;                    }                });    }}

使用:

public static void main(String[] args) {        ProxyFactory proxyFactory = new ProxyFactory(new TeacherDao());        //获取代理对象(JDK帮我们生成的)        ITeacherDao proxyIntance = (ITeacherDao) proxyFactory.getProxyIntance();        proxyIntance.teach("张三");    }

动态代理生成代理对象其实也实现了接口,和静态一样。不一样是代理对象是JDK帮我们做了而已

cglib代理

cglib代理,如果说目标类是不需要实现任何接口的,那么就用不了动态代理,但是cglib代理可以解决

注意cglib是一个框架包,需要咨询引入使用。下面直接上代码:目标类:

public class TeacherDao{    public String teach(String person) {        return person + "在教书";    }}

代理工厂类:

public class ProxyFactory implements MethodInterceptor {    private Object targetObj;    public ProxyFactory(Object targetObj){        this.targetObj = targetObj;    }    public Object getProxyIntance(){        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(targetObj.getClass());//设置父类,cglib原理就是通过继承目标类来生成子类(代理类)        enhancer.setCallback(this);        return enhancer.create();    }    @Override    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {        System.out.println("cglib增强,增强前----");        Object returnValue = method.invoke(targetObj, args);        System.out.println(returnValue);        System.out.println("cglib增强,增强后----");        return returnValue;    }}

使用

public static void main(String[] args) {        ProxyFactory proxyFactory = new ProxyFactory(new TeacherDao());        //获取代理对象(JDK帮我们生成的)        TeacherDao proxyIntance = (TeacherDao) proxyFactory.getProxyIntance();        proxyIntance.teach("张三");    }
模板模式

模板模式很简单,就是定义了一套流程所需的接口和并且子类实现。比如RedisTemplate,JdbcTemplate

标签:

Java:一篇学好设计模式_世界热点评

2023-04-13

老照相馆和它的老伙计

2023-04-13

泉州新天城市广场停车场一辆无牌四轮电动车长期占用公共车位

2023-04-13

世界观点:河源出台“金融19条”支持经济高质量发展

2023-04-13

每日快报!潮人文化节唱响潮语名曲

2023-04-13

全球热资讯!韩媒:韩将向美出借155毫米炮弹,供货量可能达33万至50万枚

2023-04-13

互联网医疗板块4月12日涨0.84%,银江技术领涨,北向资金增持5.86亿元 全球播资讯

2023-04-13

世界聚焦:赖特:阿森纳需度过困难期,对阵曼城纽卡和切尔西都不容易

2023-04-13

糖尿病视网膜病变学术会议在株洲圆满举办

2023-04-12

硅片切片产能再扩充 高测股份拟投资50亿元建设产线-今头条

2023-04-12

今日视点:少年的你如此美丽txt全文下载-少年的你如此美丽txt

2023-04-12

博俊科技:一季度净利预增80%-110% 每日讯息

2023-04-12

2022天津市滨海新区部分事业单位招聘体检、考察阶段工作安排

2023-04-12

回忆录——龙珊篇

2023-04-12

全球微速讯:中免集团深度参与消博会 见证中国旅游零售市场创新活力

2023-04-12

天天微动态丨美国一女警狂发“不雅短信”撩7名男同事,丈夫愤而举报

2023-04-12

深圳2023年5月普通话测试报名通知(时间+名额+入口) 环球今头条

2023-04-12

世界快看点丨女性消费力洞察报告

2023-04-12

和讯个股快报:2023年04月12日 山石网科(688030)11:21分,股价快速拉升 全球播报

2023-04-12

越剧现代戏《绿水青山》在京上演|当前最新

2023-04-12

3月份CPI环比下降、PPI环比持平 物价运行总体平稳|全球观速讯

2023-04-12

财面儿丨远洋集团:前3月累计实现协议销售额约165.5亿元 同比增长9.8%

2023-04-12

全球新动态:超高的颜值配合混动系统,试驾长安UNI-V智电iDD

2023-04-12

2023,新能源车圈大佬“放炮”语录

2023-04-12

在iOS推出两年后,Microsoft Whiteboard终于进入了Android_天天通讯

2023-04-12

六孔竖笛怎么吹小星星 六孔竖笛怎么吹

2023-04-12

世界观焦点:关于消防的绘画作品 一等奖

2023-04-11

环球观焦点:知名经济学家:美经济衰退和滞胀风险加大

2023-04-11

重庆山城步道在哪里?

2023-04-11

滨化股份:预计2023年1-3月盈利,净利润同比减80.63%左右

2023-04-11

Copyright ©  2015-2022 华南频道网版权所有  备案号:粤ICP备18025786号-52   联系邮箱: 954 29 18 82 @qq.com