常用设计模式的正确应用
创始人
2025-05-28 21:37:26
0

原型模式使用场景

细胞分列式的New出大量重复对象

未优化时代码:

开发代码中常见的循环赋值装载进集合的代码,这段代码在大多数场景下是没问题的,但是在要求高性能的场景下可能存在性能不好的情况

代码逻辑其实很简单就是new对象赋值装载到List中

public class BokeTest {public static void main(String[] args){List list = new ArrayList<>();for(;;){User user = new User();user.setId( new Random().nextLong() );user.setName( "xxx" );list.add( user );}}
}

优化后的代码:

原型模式 & 对象工厂优化:

通过浅拷贝的方式来变大量new实例化的过程,new关键字的运行过程可以参考对象生成的过程 (加载-验证-准备-解析-初始化),浅拷贝的过程就简单很多了(值传递)

@Data
@ToString
public class User implements Cloneable{private Long id;private String name;//实现浅拷贝@Overrideprotected User clone() throws CloneNotSupportedException {return (User) super.clone();}
}
/** * 

Title:用户对象生成工厂

*

Description:

* * @author QIQI * @date*/public class UserFactory {//只需要new一次对象private static User userProtoType = new User();public static User getInstance() throws CloneNotSupportedException {User user = userProtoType.clone();return user;} } public class BokeTest {public static void main(String[] args) throws CloneNotSupportedException {List list = new ArrayList<>();for(;;){User userX = UserFactory.getInstance();userX.setId( new Random().nextLong() );userX.setName( "xxx" );list.add( userX );}} }

结论:

某个接口QPS高 & RT要求很低,这个时候可以对代码的new实例化进行优化加速性能,但是需要注意的是对象必须属性不包含其他引用对象,不然浅拷贝是有隐藏BUG的需要使用深拷贝,深拷贝常用的方式是序列化和反序列化进行加速

装饰模式使用场景:

多态化的综合使用,针对不同功能进行多态化的抽象,将原始行为层层组装包裹对外展现统一的调用入口

业务需求:

化妆功能,完成化妆后可以展现化妆后的样貌
第一期实现涂口红的化妆功能
第二期实现涂眼影功能
未优化时代码:

下面代码是我们大多数开发的实现方式,将涂口红、涂眼影的逻辑抽成2个私有方法,入口代码组装在统一输出化妆后样貌,如果需求未来不发生变化和不需要迭代的话这样的代码也没什么问题,只是大多数情况功能需求都是会发生迭代的


1.假设涂口红的逻辑越来越复杂,需要针对不同品牌、不同色号、不同干湿度来进行更加多样的的化妆后样貌展现,这个时候涂口红的私有方法会越来越庞大,就算再拆几个私有方法出来也无法解决整个分支判断代码的无法可读性
2.假设show的展现方式也越来越丰富,那么最终show的代码也需要很多判断逻辑来选择调用那种show
//口红model
@Data
@ToString
public class Rouge{//颜色private String colour;//湿润度private String wetness;}
//眼影model
@Data
@ToString
public class EyeShadow{//颜色private String colour;}
/*
* 

Title:根据传入的口红品牌给女孩上口红

*

Description:

* @author QIQI * @params [rougeBrand] * @return void * @throws * @date 2023/03/13 18:25 */ private static void girlRouge(RougeBrand rougeBrand){//女孩上口红逻辑System.out.println("xxx使用了口红功能,色号:" + rougeBrand.getColour() + ",湿润度:" + rougeBrand.getWetness());} /* *

Title:根据传入的口红品牌给女孩上口红

*

Description:

* @author QIQI * @params [rougeBrand] * @return void * @throws * @date 2023/03/13 18:25 */ private static void girl EyeShadow(EyeShadow eyeShadow){ //女孩涂眼影逻辑System.out.println("xxx使用了眼影功能");} public static void main(String[] args) throws CloneNotSupportedException {girlRouge() + EyeShadow();//完成了化妆动作后进行展现show(); }

上面的代码因为二期的迭代在不同的私有方法中都加入了新的实现以及最终加了一个是否加分的判断逻辑,如果继续迭代下去功能越来越复杂此时代码会很难维护(修改一个小逻辑可能影响全局判断)

优化后的代码:

/** * 

Title:化妆功能基类接口

*

Description: * 抽象基础功能接口 *

* * @author QIQI * @date*/public interface DecoatorI {/**

Title:化妆完成后展示定义

*

Description:

* @author QIQI* @params []* @return void* @throws* @date 2023/03/14 20:28*/void show();} /** *

Title:化妆装饰抽象装饰类

*

Description:

* * @author QIQI * @date*/public abstract class Decoator implements DecoatorI {DecoatorI decoatorI;public Decoator(DecoatorI decoatorI) {this.decoatorI = decoatorI;}@Overridepublic void show() {decoatorI.show();} } /** *

Title:抽象实现,普通场景的show实现

*

Description:

* * @author QIQI * @date*/public class CommonShow implements DecoatorI {@Overridepublic void show() {System.out.println("普通展示");} } public interface RougeService{/**

Title:口红接口定义

*

Description:

* @author QIQI* @params [rougeBrand]* @return void* @throws* @date 2023/03/14 15:39*/void rouge(Rouge rouge);} /***

Title:口红定义,不同品牌不同子类实现

*

Description:

* @author QIQI* @date * */public interface RougeService{/**

Title:口红接口定义

*

Description:

* @author QIQI* @params [rougeBrand]* @return void* @throws* @date 2023/03/14 15:39*/void rouge(Rouge rouge);} /** *

Title:X品牌口红实现

*

Description:

* * @author QIQI * @date*/public class BrandXRougeServiceImpl extends Decoator implements RougeService{private Rouge rouge;public BrandXRougeServiceImpl(DecoatorI decoatorI,Rouge rouge) {super( decoatorI );this.rouge = rouge;}@Overridepublic void show() {//用了品牌X的口红rouge(rouge);//展现状态decoatorI.show();}@Overridepublic void rouge(Rouge rouge) {System.out.println("品牌X的口红实现");} } public class BokeTest {public static void main(String[] args) throws CloneNotSupportedException {Decoator decoator = new BrandXRougeServiceImpl( new CommonShow(),new Rouge() );decoator.show();} }

整个结构图如下,拆分描述:

  • DecoatorI 被装饰类,里面有一个show方法等待子类实现,只定义了最后需要有一个展示行为,但是过程是什么样的被装饰类不清楚

  • Decoator 装饰类,实现了被装饰类的show方法,但是也只是抽象实现,并没有具体逻辑,真正的show逻辑还是需要子类完成

  • 为什么要抽象实现show方法呢,原因是因为为了节省时间使用了最简单的案例说明,如果是复杂需求可能会存在show1、show2、show3等等多种展示形式,那么如果不通过抽象实现的话就会造成所有子类都要实现每一个show,比如口红行为只需要show1

  • CommonShow 普通show的实现,可以有多种show的实现,最终传进Decoator装饰类和不同化妆品进行组装嵌套输出

  • RougeService 口红的行为定义,这里再次扩展了多态的可能,不同品牌的口红效果可能不一样,案例随便实现了一个X品牌的口红

策略模式的使用场景:

1、许多相关的类仅仅是行为有异;
2、一个类定义了多种行为,并且这些行为在类的操作中以多个条件语句的形式出现。

未优化时代码:

根据入参来判断执行哪段私有方法逻辑,这种场景其实在我们实战中很常见,也并不是说所有的类似场景都要改成策略模式,因为策略模式的缺点就是子类太多,个人建议这种分支逻辑在 >= 3 && <=10 的时候优化成策略模式,分支逻辑太少没有优化必要反而增加复杂度,分支逻辑太多可以考虑使用门面 + 策略的结合模式

public static void main(String[] args) {String x = "";if(x.equals( "招商银行" )){System.out.println("逻辑1");}if(x.equals( "浦发银行" )){System.out.println("逻辑2");}if(x.equals( "上海银行" )){System.out.println("逻辑3");}if(x.equals( "中国银行" )){System.out.println("逻辑4");}if(x.equals( "工商银行" )){System.out.println("逻辑5");}
}

优化后的代码:

/** * 

Title:银行处理逻辑抽象定义

*

Description:

* * @author QIQI * @date*/public abstract class AbstractBankAssembleStrategy {/**

Title:定义行为的结果,子类实现过程

*

Description:

* @author QIQI* @params []* @return void* @throws* @date 2023/03/15 17:56*/public abstract void exe();} /** *

Title:中国银行的实现

*

Description:

* * @author QIQI * @date*/public class ChinaBankAssembleStrategy extends AbstractBankAssembleStrategy{@Overridepublic void exe() {System.out.println("中国银行处理");} } /** *

Title:上海银行的实现

*

Description:

* * @author QIQI * @date*/public class ShangHaiBankAssembleStrategy extends AbstractBankAssembleStrategy{@Overridepublic void exe() {System.out.println("上海银行处理");} } /** *

Title:策略的分发器

*

Description:

* * @author QIQI * @date*/public class StrategyContext {private static HashMap strategyHashMap = new HashMap<>();static { strategyHashMap.put( "china",new ChinaBankAssembleStrategy() );strategyHashMap.put( "shanghai",new ShangHaiBankAssembleStrategy() );}public static void strategrExe(String bankName){ strategyHashMap.get( bankName ).exe();} } public static void main(String[] args) {String x = "";StrategyContext.strategrExe( x );}

策略模式结构还是比较简单易懂的,可以看到上面优化完成后已经没有if判断分支的代码了

责任链的使用场景:

1、多个对象可以处理同一个请求,但具体由哪个对象处理则在运行时动态决定。
2、在请求处理者不明确的情况下向对个对象中的一个提交一个请求。
3、需要动态处理一组对象处理请求。

未优化时的代码:

public static void main(String[] args) {//调用A方法doTask-A();//如果条件成立调用B方法if(xx){doTask-B();}//在调用C方法doTask-C();}

优化后的代码:

/** * 

Title:责任链的抽象定义

*

Description:

* * @author QIQI * @date*/public abstract class AbstractHandler {@Setterprotected AbstractHandler success;public abstract void doTask();public void next() {if (success != null) {success.doTask( );}} } /** *

Title:A逻辑实现

*

Description:

* * @author QIQI * @date*/public class TaskAHandler extends AbstractHandler{@Overridepublic void doTask() {System.out.println("执行A逻辑");next();} } /** *

Title:B逻辑实现

*

Description:

* * @author QIQI * @date*/public class TaskBHandler extends AbstractHandler{@Overridepublic void doTask() {if(xxx){System.out.println("执行B逻辑");}next();} } /** *

Title:C逻辑实现

*

Description:

* * @author QIQI * @date*/public class TaskCHandler extends AbstractHandler{@Overridepublic void doTask() {System.out.println("执行C逻辑");next();} } /** *

Title:责任链的触发顺序组装

*

Description:

* * @author QIQI * @date*/public class HandlerEvent {private AbstractHandler aHandler = new TaskAHandler();private AbstractHandler bHandler = new TaskBHandler();private AbstractHandler cHandler = new TaskCHandler();/**

Title:链式组装类,决定了责任链的固定执行顺序

*

Description:

* @author QIQI* @params []* @return void* @throws* @date 2023/03/15 18:45*/public void exe(){aHandler.setSuccess( bHandler );bHandler.setSuccess( cHandler );cHandler.setSuccess( null );} } public static void main(String[] args) {HandlerEvent handlerEvent = new HandlerEvent();handlerEvent.exe();}

模板模式使用场景:

架构师常用的设计方式,定义最顶层的接口定义,再由不同开发进行实现,最终通过模板在组装起来

业务需求:

鱼可以在水里游
人可以在陆地行走
不同生物都有特有的能力,但是都必须吃饭

未优化时代码:

class Fish{public void move(){System.out.println("鱼可以在水里游");}public void eat(){System.out.println("鱼需要吃东西");}//游和吃构建了鱼的生命public void live(){move();eat();}
}
class Human{public void move(){System.out.println("人可以在陆地走");}public void eat(){System.out.println("人需要吃东西");}//走和吃构建了人的生命public void live(){move();eat();}
}

吃是各种生命体的基础条件,每一个live生命都需要eat,如果每一个生命体都这么写代码会很冗余,那么就需要抽象了

优化后的代码:

public abstract class Life {/** 

Title:行动抽象

*

Description:

* @author QIQI* @params []* @return void* @throws* @date 2023/03/15 19:44*/public abstract void move();/**

Title:吃抽象

*

Description:

* @author QIQI* @params []* @return void* @throws* @date 2023/03/15 19:44*/public abstract void eat();/**

Title:模板,所有子类都必须以此为模板

*

Description:加上final为了避免被子类重写,这个是不可改变的基础模板

* @author QIQI* @params []* @return void* @throws* @date 2023/03/15 19:44*/public final void life(){move();eat();} } //鱼的实现 public class Fish extends Life{@Overridepublic void move(){System.out.println("鱼可以在水里游");}@Overridepublic void eat(){System.out.println("鱼需要吃东西");} } //人的实现 public class Human extends Life {@Overridepublic void move(){System.out.println("人可以在陆地走");}@Overridepublic void eat(){System.out.println("人需要吃东西");} } public static void main(String[] args) {Life life = new Fish();life.life();}

模板模式就是将多态化的东西抽象成接口交给子类实现,将不可改变的行为定义成模板方法,严格限制子类实现,这样对外展示的life方法内部基础元素都未发生变化,但是又形成了实现的多态化

适配器模式使用场景:

1.系统需要使用现有的类,而此类的接口不符合系统的需要,即接口不兼容
2.想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的一些类一起工作
3.需要一个统一的输出接口,而输入端的接口不可预知
JDBC驱动包就是最常见的适配器模式设计,JDBC协议可以兼容适配mysql、oracle、sqlserver等等数据库

案例场景:

某品牌游戏机的充电器是两相口充电器
某酒店的插座是三相充电口

上面这个场景就会导致游戏机无法充电,那么生活中我们就会去买个转换器来对这种场景进行兼容,那么在代码中其实也是一个道理

模型代码:

/** * 

Title:游戏机两相充电口的接口定义

*

Description: * 主要是需要明确定义输出 *

* * @author QIQI * @date*/public interface DualPin {/**

Title:a/b代表两相口每个口的参数

*

Description:两相口为火线、零线

* @author QIQI* @params [a, b]* @return void* @throws* @date 2023/03/16 9:57*/void electrify(int a,int b);} /** *

Title:两相口的游戏机

*

Description:

* * @author QIQI * @date*/public class GameMachines implements DualPin{@Overridepublic void electrify(int a, int b) {System.out.println("两相口的游戏机充电实现");} } /** *

Title:酒店三相充电口的接口定义

*

Description: * 主要是需要明确定义输出 *

* * @author QIQI * @date*/public interface TriplePin {/**

Title:a/b/c代表三相口每个口的参数

*

Description:三相口为火线、零线、地线

* @author QIQI* @params [a, b, c]* @return void* @throws* @date 2023/03/16 9:57*/void electrify(int a,int b,int c);} /** *

Title:适配器

*

Description:

* * @author QIQI * @date*/public class Adapter implements TriplePin{//游戏机两相口接口对象private DualPin dualPin;/**

Title:初始化适配器时将两相口的实现放进来

*

Description:

* @author QIQI* @params [dualPin]* @return* @throws* @date 2023/03/16 10:14*/public Adapter(DualPin dualPin) {this.dualPin = dualPin;}/**

Title:实现三相口的方法

*

Description:

* @author QIQI* @params [a, b, c]* @return void* @throws* @date 2023/03/16 10:15*/@Overridepublic void electrify(int a, int b, int c) {//直接忽略三相口的地线参数dualPin.electrify( a,b );} } public static void main(String[] args){DualPin dualPin = new GameMachines();//两相口游戏机实现传到三相口的适配器TriplePin triplePin = new Adapter( dualPin );//调用三相口的充电方法triplePin.electrify( 0,1,2 );}

相关内容

热门资讯

安卓手机系统比较大,庞大生态下... 你有没有发现,最近你的安卓手机越来越慢了?是不是觉得打开应用、滑动屏幕都变得不那么顺畅了呢?这可不是...
安卓开发板刷系统教程,安卓开发... 你有没有想过,你的安卓开发板其实就像是一台超级电脑,只要给它换上新的操作系统,就能焕发出全新的活力呢...
安卓系统帧数显示器,深度解析帧... 你有没有想过,你的安卓手机屏幕上那些流畅的画面背后,其实隐藏着一个神秘的小助手——安卓系统帧数显示器...
安卓系统安装苹果游戏,跨平台体... 你知道吗?现在这个时代,科技的发展真是让人眼花缭乱。手机,这个小小的玩意儿,已经成为了我们生活中不可...
安卓系统移动文件失败,探究原因... 最近是不是你也遇到了安卓系统移动文件失败的问题?别急,让我来给你详细说说这个让人头疼的小麻烦,让你一...
苹果系统好友教程安卓版,轻松迁... 你是不是也和我一样,对苹果系统和安卓系统之间的互动充满了好奇?想象你的苹果手机里存满了珍贵的照片和联...
安卓车载系统盒子怎么用,轻松提... 你有没有想过,你的安卓手机那么智能,为什么不开辟一下新天地,让它也来驾驭一下你的爱车呢?没错,今天就...
安卓平板可以刷学生系统,便捷学... 你有没有想过,你的安卓平板竟然也能变身成为学生专用系统?没错,你没听错!在这个信息爆炸的时代,科技的...
中国太保软件安卓系统,智能保障 你知道吗?最近我在手机上发现了一个超级好用的软件,它就是中国太保的安卓系统版!是不是听起来就让人心动...
安卓系统低音炮系统升级,尽享沉... 你有没有发现,你的安卓手机最近是不是有点不一样了?音质好像更棒了,低音炮的感觉更足了?别惊讶,这可是...
双系统彻底删除安卓,全面解析与... 你有没有想过,你的手机里藏着一个秘密世界?没错,就是那个你几乎每天都在用的安卓系统。但是,你知道吗?...
安卓7_1开源系统,创新与优化... 你知道吗?在科技的世界里,每一步的进步都像是在翻山越岭,而安卓7.1开源系统,就是那座被我们一步步攀...
索尼系统是安卓的吗,安卓之魂的... 索尼系统是安卓的吗?亲爱的读者们,你是否曾在选购手机时,对各种操作系统感到困惑?今天,我们就来聊聊一...
安卓系统卡怎么清理垃圾,恢复流... 手机用久了是不是感觉越来越卡?尤其是安卓系统,有时候打开个应用都慢吞吞的,真是让人头疼。别急,今天就...
无纸化会议系统安卓平板,高效便... 你有没有想过,在未来的会议中,不再需要堆积如山的文件,不再需要翻找笔和纸,一切都变得轻松便捷?这就是...
手机ios系统和安卓系统哪个好... 说到手机操作系统,你是不是也和我一样,对iOS和安卓系统哪个更好用,心里有点小纠结呢?毕竟,这两个系...
安卓系统占用101gb,安卓系... 手机里的安卓系统突然告诉你,它占用了101GB的空间!是不是瞬间感觉自己的手机像吹气球一样膨胀了?别...
小米安卓4.4双系统,深度解析... 你有没有想过,手机里的系统也能玩出花来?今天,就让我带你一探究竟,看看小米安卓4.4双系统到底是个啥...
荣耀10安卓9系统包,解锁更多... 你知道吗?最近手机圈里可是热闹非凡呢!荣耀10这款手机,自从升级到了安卓9系统包,简直就像脱胎换骨了...
安卓原生系统有x号,解锁X号神... 你知道吗?最近在手机圈里,安卓原生系统可是掀起了一股热潮。听说安卓原生系统已经有X号版本了,这可真是...