设计模式-结构型模式

前面提到创建对象的模式应用,权衡模式的考虑因素有对象的唯一性、可替代性、可扩展性、对象关系、对象组件的初始化顺序等。唯一对象采用单例模式,注重效率可采用原型模式,有可替代性的对象可采用工厂模式、多工厂有关系的可以采用抽象工厂模式、多组件的复杂对象可采用建造者模式等。

今天讲解一下设计模式中的结构型模式。

抛开设计模式不提,我们讲一讲系统中类的结构。

1. 以UserDto.java为例,只有数据表字段作为成员变量,用于与数据库交互,这差不多是最简单的类结构了。

2. 当我们封装页面表单数据时,我们可能会考虑创建UserVo来继承UserDto;当我们封装业务方法的参数时,我们可能会考虑创建UserBo来继承UserDto;当我们封装查询条件时,我们可能会考虑创建UserQuery来继承UserDto;这是一种继承结构。

3. 继承不太好用,原因是修改基类会影响所有子类,多层继承不好维护,那么:

3.1 当我们需要调用某个类,还不想或不能去修改它,又需要加以控制时,可以考虑代理模式;

3.2 当我们需要调用某个类,还不想或不能去修改它,又需要给它添加属性或增强功能时,可以考虑装饰器模式;

3.3 当我们需要调用某个类,还不想或不能去修改它,又需要适配某个目标接口时,可以考虑适配器模式;

3.4 当我们需要调用某个类,还不想或不能去修改它,又需要向外界发布接口时,可以考虑外观模式;

上面提到了4种结构型模式,可以代替继承来满足相应的场景需求。 具体的实体代码不用拘泥于形式,下面只是简单示例:

a. 假设A.a()是已有的类和方法,则创建Agent类,以A为子对象,Agent中的方法调用A.a(),再选择性地附加一些安全、缓存等控制,即完成了代理模式的实现。

b.假设A.a()是已有的类和方法,则创建Decorator抽象类,以A为构造参数,以A.a()为方法体创建Decorator.a(),之后,以Decorator为基类,就可以创建各种子类,并追加属性或方法。这就是装饰器模式,Decorator抽象类可有可无,加入进来是为了固定模式和方便复用。

c.假设A.a()是已有的类和方法,B.b()是目标接口, 则创建接口B和方法B.b(),其中B.b()中调用A.a()方法,这是最简单的适配器模式的实现。假设B.b()要实现多个已有的方法,可以通过参数来决定时调用哪种方法。

d.假设A.a(),B.b(), C.c()需要发布给外界调用,则创建接口Y, 提供3个方法:Y.a(), Y.b(), Y.c(),分别调用现有的方法,通常,外观模式对现有方法的封装,在方法名、参数和返回值方面,都会有相关的规范,例如统一数据格式、方法名的规范性、结果集作为返回值等。

4. 说完了继承的4种代替模式,接下来看看另外4种特殊场景下才会用到的结构型模式。

4.1 当创建的对象是树形结构时,可以考虑使用组合模式。

树形菜单可以把子菜单作为component保存在对象的一个List中,部门可以把子部门作为component保存在一个List中。这就是组合模式,它将对象组合成树形结构,以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

4.2 桥接模式是一种数据(实体)和行为(抽象)没有分离的设计模式,它将行为接口作为实体基类的构造参数,将行为接口的实体类作为实体子类的构造参数,以此来拥抱抽象和实体的变化。但是,在提倡实体数据和抽象行为分离的设计潮流中,大家更喜欢把实体基类作为参数传入抽象接口中,像反过来将抽象接口作为成员传入实体基类的设计很少见了。
可见,只有项目实际场景特别契合,或者已有代码通过桥接模式修改特别轻松时,才会用到桥接模式。

4.3 当需要按不同属性值来创建各自唯一的实例时,可以考虑使用亨元模式

以Ball.java为例,其中有属性color,如果要求每一种color的Ball只有一个实例,此时可以考虑用亨元模式,创建BallFactory,里面有一个HashMap<String color, Ball ball>来保存不同颜色的实例,为color作为工厂方法的参数,再hashMap中找Ball对象,找不到就new,找到就返回。这样避免了每次都new对象造成的浪费,也可以追踪Ball对象的属性变化情况。 

4.4 当需要按对象属性来过滤一组对象时,可以考虑使用过滤器模式。
假设有很多种产品,保存在List<Product>中,采用过滤器模式, 则可以定义一个Criteria.filter()的标准过滤方法,实现此接口来创建各种过滤器,例如EastProductCriteria.filter()用来过滤华东的产品,WestProductCriteria.filter()用来过滤华西的产品, NewProductCriteria.filter()用来过滤新产品,OldProductCriteria.filter()用来过滤老产品,AndCriteria.filter(Criteria... criterias)、OrCriteria.filter(Criteria... criterias)用来多条件过滤。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值