门面模式与装饰器模式
- 门面模式
- 应用场景
- 通用类图
- 案例演示
- 源码应用
- 装饰器模式
- 应用场景
- 通用类图
- 案例演示
- 煎饼果子案例
- 增强日志案例
- 源码应用
- 作业
门面模式
门面模式又叫外观模式,提供了一个统一的接口,用来访问子系统中的一群接口。其主要特征是定义了一个高层接口,让子系统更容易使用,属于结构型模式。
应用场景
1.子系统越来越复杂,增加门面模式提供简单接口。
2.构建多层系统结构,利用门面对象作为每层的入口,简化层间调用。
通用类图
门面模式一般包含两种角色:
-
外观角色(Facade):也称门面角色,系统对外的统一接口
-
子系统角色(SubSystem):可以拥有一个或多个SubSystem
案例演示
积分兑换礼品:分为三个步骤,①判断积分是否足够②支付积分③获取物流单号
在不引用外观模式时,前端需要先访问积分系统判断用户积分是否足够,其次需要访问支付系统进行支付,支付完成后需要访问物流系统获取单号;这种方式一来增加了前端开发的工作,二来因为多个网络请求影响了页面的性能。
礼品信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14public class GiftInfo { private String name; public GiftInfo(String name) { this.name = name; } public String getName() { return name; } }
判断积分是否足够 子系统角色
1
2
3
4
5
6
7
8public class QualifyService { public boolean isAvailable(GiftInfo giftInfo){ System.out.println("校验" +giftInfo.getName() + "积分通过,库存通过。"); return true; } }
支付积分 子系统角色
1
2
3
4
5
6
7
8public class PaymentService { public boolean pay(GiftInfo giftInfo){ System.out.println("扣减" + giftInfo.getName() + " 积分成功"); return true; } }
获取物流单号 子系统角色
1
2
3
4
5
6
7
8public class ShippingService { public String delivery(GiftInfo giftInfo){ System.out.println(giftInfo.getName() + "进入物流系统"); String shippingNo = "666"; return shippingNo; } }
门面角色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public class FacadeService { private QualifyService qualifyService = new QualifyService(); private PaymentService paymentService = new PaymentService(); private ShippingService shippingService = new ShippingService(); public void exchange(GiftInfo giftInfo){ if(qualifyService.isAvailable(giftInfo)){ if(paymentService.pay(giftInfo)){ String shippingNo = shippingService.delivery(giftInfo); System.out.println("物流系统下单成功,物流单号是:" + shippingNo); } } } }
源码应用
spring-jdbc下的JdbcUtils:封装了一系列跟数据库操作有关的方法
Mybatis中的Configuration
装饰器模式
装饰器模式也称为包装模式,是指在不改变原有对象的基础上,将功能附加到对象上,提供了比继承更有弹性的
替代方案(扩展原有对象的功能),属于结构型模式。
装饰器模式的核心是功能扩展。使用装饰器模式可以透明且动态的扩展类的功能。
应用场景
1.用于扩展一个类的功能或给一个类添加附加职责
2.动态的给一个对象添加功能,这些功能可以在动态的撤销
实际场景:煎饼果子加鸡蛋加热狗;房子装修刷漆贴墙纸贴瓷砖;吃火锅加各种调料。
通用类图
装饰器模式一般包含四种角色:
- 抽象组件(Component):充当被装饰类的原始对象,规定了被装饰对象的行为。
- 具体组件(ConcreteComponent):抽象组件的实现或子类,也即被装饰对象。
- 抽象装饰器(Decorator):抽象类,提供构造函数注入抽象组件引用。
- 具体装饰器(ConcreteDecorator):Decorator的子类,提供扩展功能。
案例演示
煎饼果子案例
存在以下场景,买煎饼果子的时候,可以选择性的加鸡蛋,加香肠,通过装饰器模式实现以上场景。
抽象组件
1
2
3
4
5public abstract class Battercake { protected abstract String getMsg(); protected abstract int getPrice(); }
具体组件 煎饼
1
2
3
4
5public class BaseBattercake extends Battercake{ protected String getMsg(){ return "煎饼";} public int getPrice(){ return 5;} }
抽象装饰器
1
2
3
4
5
6
7
8
9
10public class BattercakeDecorator extends Battercake{ private Battercake battercake; public BattercakeDecorator(Battercake battercake) { this.battercake = battercake; } protected String getMsg(){ return this.battercake.getMsg();} public int getPrice(){ return this.battercake.getPrice();} }
具体装饰器 加鸡蛋
1
2
3
4
5
6
7
8
9public class EggDecorator extends BattercakeDecorator{ public EggDecorator(Battercake battercake) { super(battercake); } protected String getMsg(){ return super.getMsg() + "1个鸡蛋";} public int getPrice(){ return super.getPrice() + 1;} }
具体装饰器 加香肠
1
2
3
4
5
6
7
8
9public class SauageDecorator extends BattercakeDecorator{ public SauageDecorator(Battercake battercake) { super(battercake); } protected String getMsg(){ return super.getMsg() + "1根香肠";} public int getPrice(){ return super.getPrice() + 2;} }
增强日志案例
当前日志打印采用log4j+slf4j搭建而成,需求是希望打印出来的日志是json格式的。
由上述可知当前抽象组件是Logger,具体组件通过LoggerFactory.getLogger()得到,因此需要创建抽象装饰器(当前案例可省略)和具体装饰器。
抽象装饰器
1
2
3
4
5
6
7
8
9public class LoggerDecorator implements Logger { protected Logger logger; public LoggerDecorator(Logger logger) { this.logger = logger; } //省略需实现方法 }
具体装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32public class JsonLoggerDecorator extends LoggerDecorator { public JsonLoggerDecorator(Logger logger) { super(logger); } @Override public void info(String s) { JSONObject result = newJsonObject(); result.put("message",s); logger.info(result.toString()); } @Override public void error(String s) { JSONObject result = newJsonObject(); result.put("message",s); logger.info(result.toString()); } public void error(Exception e){ JSONObject result = newJsonObject(); result.put("exception",e.getClass().getName()); String trace = Arrays.toString(e.getStackTrace()); result.put("starckTrace",trace); logger.info(result.toString()); } private JSONObject newJsonObject(){ return new JSONObject(); } }
为减少需要修改的地方,新建JsonLoggerFactory以替代LoggerFacatory
1
2
3
4
5
6
7
8
9public class JsonLoggerFactory { public static JsonLoggerDecorator getLogger(Class clazz){ //具体组件 Logger logger = LoggerFactory.getLogger(clazz); //包装具体组件 return new JsonLoggerDecorator(logger); } }
源码应用
InputStream : 文件流作为一个具体组件,对象流、缓存流、数据流作为具体装饰器。
spring中的事务缓存TransactionAwareCacheDecorator 、mvc中的ServerHttpResponseDecorator:标准抽象装饰器
以及mybatis包中org.apache.ibatis.cache.decorators的很多类
作业
根据权限的不同动态增加导航栏标题
抽象组件
1
2
3
4
5
6
7
8
9
10public abstract class AbstractTitle { /** * 获取标题 * **/ public String[] getTitles(){ return null; } }
具体组件
1
2
3
4
5
6
7public class BaseTitle extends AbstractTitle { @Override public String[] getTitles() { return new String[]{"问答","文章","精品课","冒泡","商城"}; } }
抽象装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25public abstract class AbstractTitleDecorator extends AbstractTitle{ protected AbstractTitle abstractTitle; protected AbstractTitleDecorator(AbstractTitle abstractTitle){ this.abstractTitle = abstractTitle; } @Override public String[] getTitles() { return abstractTitle.getTitles(); } /** * 增加标题 * **/ protected String[] addTitle(String titleName){ String[] titles = abstractTitle.getTitles(); String[] res = new String[titles.length + 1]; System.arraycopy(titles,0,res,0,titles.length); res[res.length - 1] = titleName; return res; } }
具体装饰器 作业
1
2
3
4
5
6
7
8
9
10
11public class HomeWorkTitleDecorator extends AbstractTitleDecorator { public HomeWorkTitleDecorator(AbstractTitle abstractTitle) { super(abstractTitle); } @Override public String[] getTitles() { return addTitle("作业"); } }
具体装饰器 题库
1
2
3
4
5
6
7
8
9
10
11public class ExamTitleDecorator extends AbstractTitleDecorator { public ExamTitleDecorator(AbstractTitle abstractTitle) { super(abstractTitle); } @Override public String[] getTitles() { return addTitle("题库"); } }
具体装饰器 成长墙
1
2
3
4
5
6
7
8
9
10
11public class ProgressWallTitleDecorator extends AbstractTitleDecorator { public ProgressWallTitleDecorator(AbstractTitle abstractTitle) { super(abstractTitle); } @Override public String[] getTitles() { return addTitle("成长墙"); } }
最后
以上就是小巧水壶最近收集整理的关于架构师内功心法-----门面模式与装饰器模式门面模式装饰器模式的全部内容,更多相关架构师内功心法-----门面模式与装饰器模式门面模式装饰器模式内容请搜索靠谱客的其他文章。
发表评论 取消回复