我是靠谱客的博主 小巧水壶,最近开发中收集的这篇文章主要介绍架构师内功心法-----门面模式与装饰器模式门面模式装饰器模式,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

门面模式与装饰器模式

  • 门面模式
    • 应用场景
    • 通用类图
    • 案例演示
    • 源码应用
  • 装饰器模式
    • 应用场景
    • 通用类图
    • 案例演示
      • 煎饼果子案例
      • 增强日志案例
    • 源码应用
    • 作业


门面模式

门面模式又叫外观模式,提供了一个统一的接口,用来访问子系统中的一群接口。其主要特征是定义了一个高层接口,让子系统更容易使用,属于结构型模式。

应用场景

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("成长墙");
    }
}

最后

以上就是小巧水壶为你收集整理的架构师内功心法-----门面模式与装饰器模式门面模式装饰器模式的全部内容,希望文章能够帮你解决架构师内功心法-----门面模式与装饰器模式门面模式装饰器模式所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部