什么是装饰器模式
装饰器模式(Decorator Pattern)属于结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。它是作为现有的类的一个包装。
意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。
注意事项:可代替继承。
装饰器模式, 是你还有你
链接: 装饰器模式.
装饰器模式, 是你还有你
java的IO流中经常能看到装饰者模式
BufferedInputStream 和 BufferedOutputStream一样,他们都是装饰器模式下具体的装饰类。
用来装饰InputStream以及OutputStream下的其他的具体的实现类,比如FileInputStream
通过修饰器模式增强ArrayList实现构建树形结构集合
package com.zm.decorator;
import java.util.List;
/**
* 树形结构基础类
* @param <T>
*/
public interface BaseTree<T> {
String getId();
void setId(String id);
String getPid();
void setPid(String pid);
List<T> getChildren();
void setChildren(List<T> children);
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 树形结构工具类
* T 实现了BaseTree接口的实体对象,实体对象中默认有表示父子关系的id和pid
* N id和pid的类型
* 由于 实体对象中表示父子关系的属性名称不一定是id和pid,所以提供了getId和getPid方法进行拓展
*/
public abstract class TreeUtil<T extends BaseTree<T>, N> {
/**
* id的get方法
*
* @param t 对象
* @return id 的值
*/
protected abstract N getId(T t);
/**
* 父级id的get方法
*
* @param t 对象
* @return pid 的值
*/
protected abstract N getPid(T t);
/**
* 格式化成树形结构
* 要点:非基本类型的变量存储的是内存地址,对它的操作会影响到原始值。
*
* @param list 要操作的列表
* @return 树形结果列表
*/
public List<T> parseTree(List<T> list) {
if(list.isEmpty()){
return list;
}
List<T> resultList = new ArrayList<>();
// 知道有多少个元素,那么在创建的时候直接指定长度,避免因扩容而浪费时间
Map<N, T> tmpMap = new HashMap<>(list.size());
for (T t : list) {
tmpMap.put(this.getId(t), t);
}
for (T t : list) {
/*1、tmpMap存储的是以id为key的键值对。
2、如果以pid为key可以从tmpMap中取出对象,则说明该元素是子级元素。
3、如果以pid为key不能从tmpMap中取出对象,则说明该元素是最上层元素。
4、子级元素放在父级元素的children中。
5、最上层元素添加到结果中
*/
T tmap = tmpMap.get(this.getPid(t));
if (tmap != null) {
if (null == tmap.getChildren()) {
tmap.setChildren(new ArrayList<>());
}
tmap.getChildren().add(t);
} else {
resultList.add(t);
}
}
// 如果集合中存储了大量的元素,并且集合已经使用完毕,那么尽量调用clear方法来及时的释放空间。
// 如果集合不会重复使用,那么将集合也设置为null将内存一并释放。这样有助于gc能更快完成清除内存的工作。
list.clear();
list = null;
return resultList;
}
}
package com.zm.decorator;
import java.util.List;
public class TestNode implements BaseTree<TestNode>{
private List<TestNode> children;
private String id;
private String pid;
private String name;
@Override
public List<TestNode> getChildren() {
return children;
}
@Override
public void setChildren(List<TestNode> children) {
this.children = children;
}
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
this.id = id;
}
@Override
public String getPid() {
return pid;
}
@Override
public void setPid(String pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.zm.decorator;
import java.util.ArrayList;
import java.util.List;
/**
* 使用装饰者模式对ArrayList进行构建树形功能进行增强
* @author zhou
*/
public class MyTreeList<E extends BaseTree<E>> extends ArrayList<E>{
protected ArrayList<E> list;
public MyTreeList(ArrayList<E> list){
this.list = list;
}
public List<E> tree(){
TreeUtil<E, String> treeUtil = new TreeUtil<E, String>() {
@Override
protected String getId(E e) {
return e.getId();
}
@Override
protected String getPid(E e) {
return e.getPid();
}
};
return treeUtil.parseTree(list);
}
public static void main(String[] args) {
ArrayList<TestNode> objects = getTestNodes();
test2(objects);
}
private static void test2(ArrayList<TestNode> objects) {
MyTreeList<TestNode> testNodes = new MyTreeList<>(objects);
List<TestNode> tree = testNodes.tree();
System.out.println(tree);
}
private static ArrayList<TestNode> getTestNodes() {
TestNode testNode1 = new TestNode();
testNode1.setName("中国");
testNode1.setId("0");
TestNode testNode2 = new TestNode();
testNode2.setName("福建省");
testNode2.setId("1");
testNode2.setPid("0");
TestNode testNode3 = new TestNode();
testNode3.setName("浙江省");
testNode3.setId("2");
testNode3.setPid("0");
TestNode testNode4 = new TestNode();
testNode4.setName("福州市");
testNode4.setId("3");
testNode4.setPid("1");
TestNode testNode5 = new TestNode();
testNode5.setName("宁德市");
testNode5.setId("4");
testNode5.setPid("1");
ArrayList<TestNode> objects = new ArrayList<>();
objects.add(testNode1);
objects.add(testNode2);
objects.add(testNode3);
objects.add(testNode4);
objects.add(testNode5);
return objects;
}
}
项目中接口实现类使用修饰器模式增强
计算订单金额
/**
* 订单金额计算
*/
public interface OrderCalculationService {
String orderCalculation();
}
import org.springframework.stereotype.Service;
@Service("OrderCalculationServiceImpl")
public class OrderCalculationServiceImpl implements OrderCalculationService{
@Override
public String orderCalculation() {
return "订单计算价格为50元";
}
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author zhou
*/
@RestController
public class DecoratorController {
@Resource(name="OrderCalculationServiceImpl")
OrderCalculationService orderCalculationService1;
@GetMapping("order1")
public String test(){
String s = orderCalculationService1.orderCalculation();
System.out.println(s);
return s;
}
}
增强随机减免金额功能
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service("OrderCalculationReductionImpl")
public class OrderCalculationReductionImpl extends OrderCalculationServiceImpl {
private final OrderCalculationServiceImpl orderCalculationService;
public OrderCalculationReductionImpl(@Qualifier("OrderCalculationServiceImpl") OrderCalculationServiceImpl orderCalculationService) {
this.orderCalculationService = orderCalculationService;
}
public String reduction() {
// 不改动之前的逻辑 进行功能增强 也可随时取消
String s = orderCalculationService.orderCalculation();
s = "原先:" + s + ",随机减免后,订单计算价格为49.9元";
return s;
}
}
package com.zm.decorator;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author zhou
*/
@RestController
public class DecoratorController {
@Resource(name="OrderCalculationServiceImpl")
OrderCalculationService orderCalculationService1;
@Resource
OrderCalculationReductionImpl orderCalculationReduction;
@GetMapping("order1")
public String test(){
String s = orderCalculationService1.orderCalculation();
System.out.println(s);
return s;
}
@GetMapping("order2")
public String test2(){
// 现在需要新增 随机减免功能
String s = orderCalculationReduction.reduction();
System.out.println(s);
return s;
}
}