概述
门面模式与装饰器模式
- 门面模式
- 应用场景
- 通用类图
- 案例演示
- 源码应用
- 装饰器模式
- 应用场景
- 通用类图
- 案例演示
- 煎饼果子案例
- 增强日志案例
- 源码应用
- 作业
门面模式
门面模式又叫外观模式,提供了一个统一的接口,用来访问子系统中的一群接口。其主要特征是定义了一个高层接口,让子系统更容易使用,属于结构型模式。
应用场景
1.子系统越来越复杂,增加门面模式提供简单接口。
2.构建多层系统结构,利用门面对象作为每层的入口,简化层间调用。
通用类图
门面模式一般包含两种角色:
-
外观角色(Facade):也称门面角色,系统对外的统一接口
-
子系统角色(SubSystem):可以拥有一个或多个SubSystem
案例演示
积分兑换礼品:分为三个步骤,①判断积分是否足够②支付积分③获取物流单号
在不引用外观模式时,前端需要先访问积分系统判断用户积分是否足够,其次需要访问支付系统进行支付,支付完成后需要访问物流系统获取单号;这种方式一来增加了前端开发的工作,二来因为多个网络请求影响了页面的性能。
礼品信息
public class GiftInfo {
private String name;
public GiftInfo(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
判断积分是否足够 子系统角色
public class QualifyService {
public boolean isAvailable(GiftInfo giftInfo){
System.out.println("校验" +giftInfo.getName() + "积分通过,库存通过。");
return true;
}
}
支付积分 子系统角色
public class PaymentService {
public boolean pay(GiftInfo giftInfo){
System.out.println("扣减" + giftInfo.getName() + " 积分成功");
return true;
}
}
获取物流单号 子系统角色
public class ShippingService {
public String delivery(GiftInfo giftInfo){
System.out.println(giftInfo.getName() + "进入物流系统");
String shippingNo = "666";
return shippingNo;
}
}
门面角色
public 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的子类,提供扩展功能。
案例演示
煎饼果子案例
存在以下场景,买煎饼果子的时候,可以选择性的加鸡蛋,加香肠,通过装饰器模式实现以上场景。
抽象组件
public abstract class Battercake {
protected abstract String getMsg();
protected abstract int getPrice();
}
具体组件 煎饼
public class BaseBattercake extends Battercake{
protected String getMsg(){ return "煎饼";}
public int getPrice(){ return 5;}
}
抽象装饰器
public 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();}
}
具体装饰器 加鸡蛋
public class EggDecorator extends BattercakeDecorator{
public EggDecorator(Battercake battercake) {
super(battercake);
}
protected String getMsg(){ return super.getMsg() + "1个鸡蛋";}
public int getPrice(){ return super.getPrice() + 1;}
}
具体装饰器 加香肠
public 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()得到,因此需要创建抽象装饰器(当前案例可省略)和具体装饰器。
抽象装饰器
public class LoggerDecorator implements Logger {
protected Logger logger;
public LoggerDecorator(Logger logger) {
this.logger = logger;
}
//省略需实现方法
}
具体装饰器
public 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
public 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的很多类
作业
根据权限的不同动态增加导航栏标题
抽象组件
public abstract class AbstractTitle {
/**
* 获取标题
*
**/
public String[] getTitles(){
return null;
}
}
具体组件
public class BaseTitle extends AbstractTitle {
@Override
public String[] getTitles() {
return new String[]{"问答","文章","精品课","冒泡","商城"};
}
}
抽象装饰器
public 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;
}
}
具体装饰器 作业
public class HomeWorkTitleDecorator extends AbstractTitleDecorator {
public HomeWorkTitleDecorator(AbstractTitle abstractTitle) {
super(abstractTitle);
}
@Override
public String[] getTitles() {
return addTitle("作业");
}
}
具体装饰器 题库
public class ExamTitleDecorator extends AbstractTitleDecorator {
public ExamTitleDecorator(AbstractTitle abstractTitle) {
super(abstractTitle);
}
@Override
public String[] getTitles() {
return addTitle("题库");
}
}
具体装饰器 成长墙
public class ProgressWallTitleDecorator extends AbstractTitleDecorator {
public ProgressWallTitleDecorator(AbstractTitle abstractTitle) {
super(abstractTitle);
}
@Override
public String[] getTitles() {
return addTitle("成长墙");
}
}
最后
以上就是小巧水壶为你收集整理的架构师内功心法-----门面模式与装饰器模式门面模式装饰器模式的全部内容,希望文章能够帮你解决架构师内功心法-----门面模式与装饰器模式门面模式装饰器模式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复