装饰模式、适配器模式、组合模式
设计模式
结构型模式
通过组合类或对象产生更大的结构以适应更高层次的逻辑需求
装饰模式
动态的给一个对象添加一些额外的职责
四个角色
抽象构件(Component)角色
用于规范需要装饰的对象(原始对象)
/**
* 抽象构件(Component)角色
*
* @author Jenson
*/
public interface Car {
/**
* 汽车装配
*/
public void show();
}
具体构件(Concrete Component)角色
实现抽象构件接口,定义一个需要装饰的原始类
/**
* 具体构件(Concrete Component)角色
*
* @author Jenson
*/
public class BenzCar implements Car {
public void show() {
System.out.println("BenzCar 默认黑色");
}
}
装饰(Decorator)角色
角色持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口
/**
* 装饰(Decorator)角色
*
* @author Jenson
*/
public abstract class BaseCarDecorator implements Car {
private Car car;
public BaseCarDecorator(Car car) {
this.car = car;
}
public void show() {
this.car.show();
}
}
具体装饰(Concrete Decorator)角色
该角色负责对构件对象进行装饰
/**
* 具体装饰(Concrete Decorator)角色
* @author Jenson
*/
public class ConcreteCarDecorator extends BaseCarDecorator{
public ConcreteCarDecorator(Car car) {
super(car);
}
@Override
public void show() {
super.show();
this.print();
this.setGPS();
}
private void print(){
System.out.println("绘制联名logo");
}
private void setGPS(){
System.out.println("安装GPS");
}
}
调用
/**
* @author Jenson
*/
public class DecoratorMain {
public static void main(String[] args) {
Car car= new BenzCar();
BaseCarDecorator carDecorator = new ConcreteCarDecorator(car);
carDecorator.show();
}
}
代理模式和装饰模式的区别
代理模式关注于控制对对象的访问:代理类可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例
public class ProxySubject implements Subject {
private Subject subject;
public <T extends Subject> ProxySubject(Class<T> c) throws IllegalAccessException, InstantiationException {
this.subject = c.newInstance();
}
...
装饰模式关注于在一个对象上动态的添加方法:装饰模式通常的做法是将原始对象作为一个参数传给装饰者的构造器
public abstract class BaseCarDecorator implements Car {
private Car car;
public BaseCarDecorator(Car car) {
this.car = car;
}
...
适配器模式
将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作
将一个接口或类转换成其他的接口或类
使用场景
修改一个已经投产中的系统时,需要对系统进行扩展,此时使用一个已有的类,但这个类不符合系统中的接口,这时使用适配器模式是最合适的,它可以将不符合系统接口的类转换成符合系统接口的、可以使用的类
三个角色
目标(Target)角色
/**
* 目标(Target)角色
*
* @author Jenson
*/
public interface Target {
/**
* 目标角色接口函数
*/
public void request();
}
源(Adaptee)角色
/**
* 源(Adaptee)角色
*
* @author Jenson
*/
public class Adaptee {
public void specificRequest() {
System.out.println("这是一个系统中已经使用了很久的类了");
}
}
适配器(Adapter)角色
通过继承或是类关联的方式,将源角色转换为目标角色
/**
* 适配器(Adapter)角色
*
* @author Jenson
*/
public class Adapter extends Adaptee implements Target {
public void request() {
System.out.println("这是从目标接口中实现来的,通过此方式让这个类同时兼具源角色和目标角色的特性,能适配目标角色的接口");
super.specificRequest();
}
}
调用
/**
* @author Jenson
*/
public class AdapterMain {
public static void main(String[] args) {
Target adp = new Adapter();
adp.request();
}
}
组合模式
将对象组合成树形结构以表示“部分—整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性
三个角色
抽象构件(Component)角色
定义参加组合对象的共有方法和属性,规范一些默认的行为接口
/**
* 抽象构件(Component)角色
*
* @author Jenson
*/
public interface OrgComponent {
/**
* 获取信息
*
* @return 节点信息
*/
public String getInfo();
}
叶子构件(Leaf)角色
叶子对象,其下没有其他的分支,定义出参加组合的原始对象的行为
/**
* @author Jenson
*/
@Data
public class LeafOrg implements OrgComponent{
private String orgName;
private String orgCode;
public String getInfo() {
return this.toString();
}
}
树枝构件(Composite)角色
参加组合的、其下有分支的树枝对象,它的作用是将树枝和叶子组合成一个树形结构,并定义出管理子对象的方法
/**
* @author Jenson
*/
@Data
public class OrgBranch implements OrgComponent {
private List<OrgComponent> orgList = new ArrayList<OrgComponent>();
private String orgName;
private String orgCode;
public void add(OrgComponent org) {
this.orgList.add(org);
}
public void remove(OrgComponent org) {
this.orgList.remove(org);
}
public List<OrgComponent> getChild() {
return orgList;
}
public String getInfo() {
return this.toString();
}
}
调用
/**
* @author Jenson
*/
public class CompositeMain {
public static void main(String[] args) {
// 顶级节点
OrgComponent master = new OrgBranch();
((OrgBranch) master).setOrgName("大姐夫公司");
((OrgBranch) master).setOrgCode("DJF");
// 研发部门
OrgComponent RD = new OrgBranch();
((OrgBranch) RD).setOrgName("研发部门");
((OrgBranch) RD).setOrgCode("RD");
((OrgBranch) master).getChild().add(RD);
// 销售部门
OrgComponent sale = new OrgBranch();
((OrgBranch) sale).setOrgName("销售部门");
((OrgBranch) sale).setOrgCode("sale");
((OrgBranch) master).getChild().add(sale);
// 叶子节点
//软件研发
OrgComponent software = new LeafOrg();
((LeafOrg) software).setOrgName("软件研发");
((LeafOrg) software).setOrgCode("software");
((OrgBranch) RD).getChild().add(software);
//硬件研发
OrgComponent hardware = new LeafOrg();
((LeafOrg) hardware).setOrgName("硬件研发");
((LeafOrg) hardware).setOrgCode("hardware");
((OrgBranch) RD).getChild().add(hardware);
System.out.println(master.getInfo());
System.out.println(JSON.toJSONString(master));
}
}
使用场景
- 需要描述对象的部分和整体的等级结构,如树形菜单、文件和文件夹管理
- 需要客户端忽略个体构件和组合构件的区别,平等对待所有的构件
优点
- 层模块调用简单
- 节点自由增加
缺点
-
不易控制树枝构件的类型
-
不易使用继承的方法来增加新的行为
[TOC]
参考:
书名:设计模式:Java版 作者:青岛东合信息技术有限公司 出版社:电子工业出版社
https://www.cnblogs.com/jaredlam/archive/2011/11/08/2241089.html