标签:static get 管理 代理模式 参考 ima lin Stub cad
《设计模式自习室》系列,顾名思义,本系列文章带你温习常见的设计模式。主要内容有:
该系列会逐步更新于我的博客和公众号(博客见文章底部),也希望各位观众老爷能够关注我的个人公众号:后端技术漫谈,不会错过精彩好看的文章。
组合模式是为了表示那些层次结构,同时部分和整体也可能是一样的结构,常见的如文件夹或者树。
上图来自:
https://www.cnblogs.com/betterboyz/p/9356458.html
从上图可以看出,文件系统是一个树结构,树上长有节点。树的节点有两种,一种是树枝节点,即目录,有内部树结构,在图中涂有颜色;另一种是文件,即树叶节点,没有内部树结构。
组合模式定义了如何将容器对象和叶子对象进行递归组合,使得客户在使用的过程中无须进行区分,可以对他们进行一致的处理。
在使用组合模式中需要注意一点也是组合模式最关键的地方:叶子对象和组合对象实现相同的接口。这就是组合模式能够将叶子节点和对象节点进行一致处理的原因。
合成模式的实现根据所实现接口的区别分为两种形式,分别称为安全式和透明式,将在类图一节中详细介绍两种形式。
安全模式的合成模式要求管理聚集的方法只出现在树枝构件类中,而不出现在树叶构件类中。
与安全式的合成模式不同的是,透明式的合成模式要求所有的具体构件类,不论树枝构件还是树叶构件,均符合一个固定接口。
public interface Component {
/**
* 输出组建自身的名称
*/
public void printStruct(String preStr);
}
public class Composite implements Component {
/**
* 用来存储组合对象中包含的子组件对象
*/
private List<Component> childComponents = new ArrayList<Component>();
/**
* 组合对象的名字
*/
private String name;
/**
* 构造方法,传入组合对象的名字
* @param name 组合对象的名字
*/
public Composite(String name){
this.name = name;
}
/**
* 聚集管理方法,增加一个子构件对象
* @param child 子构件对象
*/
public void addChild(Component child){
childComponents.add(child);
}
/**
* 聚集管理方法,删除一个子构件对象
* @param index 子构件对象的下标
*/
public void removeChild(int index){
childComponents.remove(index);
}
/**
* 聚集管理方法,返回所有子构件对象
*/
public List<Component> getChild(){
return childComponents;
}
/**
* 输出对象的自身结构
* @param preStr 前缀,主要是按照层级拼接空格,实现向后缩进
*/
@Override
public void printStruct(String preStr) {
// 先把自己输出
System.out.println(preStr + "+" + this.name);
//如果还包含有子组件,那么就输出这些子组件对象
if(this.childComponents != null){
//添加两个空格,表示向后缩进两个空格
preStr += " ";
//输出当前对象的子对象
for(Component c : childComponents){
//递归输出每个子对象
c.printStruct(preStr);
}
}
}
}
public class Leaf implements Component {
/**
* 叶子对象的名字
*/
private String name;
/**
* 构造方法,传入叶子对象的名称
* @param name 叶子对象的名字
*/
public Leaf(String name){
this.name = name;
}
/**
* 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字
* @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
*/
@Override
public void printStruct(String preStr) {
// TODO Auto-generated method stub
System.out.println(preStr + "-" + name);
}
}
public class Client {
public static void main(String[]args){
Composite root = new Composite("服装");
Composite c1 = new Composite("男装");
Composite c2 = new Composite("女装");
Leaf leaf1 = new Leaf("衬衫");
Leaf leaf2 = new Leaf("夹克");
Leaf leaf3 = new Leaf("裙子");
Leaf leaf4 = new Leaf("套装");
root.addChild(c1);
root.addChild(c2);
c1.addChild(leaf1);
c1.addChild(leaf2);
c2.addChild(leaf3);
c2.addChild(leaf4);
root.printStruct("");
}
}
相比上面的安全式只有两处改动:
public class Composite extends Component {
...
}
public class Leaf extends Component {
...
}
public class Client {
public static void main(String[]args){
Component root = new Composite("服装");
Component c1 = new Composite("男装");
Component c2 = new Composite("女装");
Component leaf1 = new Leaf("衬衫");
Component leaf2 = new Leaf("夹克");
Component leaf3 = new Leaf("裙子");
Component leaf4 = new Leaf("套装");
root.addChild(c1);
root.addChild(c2);
c1.addChild(leaf1);
c1.addChild(leaf2);
c2.addChild(leaf3);
c2.addChild(leaf4);
root.printStruct("");
}
}
可以看出,客户端无需再区分操作的是树枝对象(Composite)还是树叶对象(Leaf)了;对于客户端而言,操作的都是Component对象。
HashMap 提供 putAll 的方法,可以将另一个 Map 对象放入自己的存储空间中,如果有相同的 key 值则会覆盖之前的 key 值所对应的 value 值
public class Test {
public static void main(String[] args) {
Map<String, Integer> map1 = new HashMap<String, Integer>();
map1.put("aa", 1);
map1.put("bb", 2);
map1.put("cc", 3);
System.out.println("map1: " + map1);
Map<String, Integer> map2 = new LinkedMap();
map2.put("cc", 4);
map2.put("dd", 5);
System.out.println("map2: " + map2);
map1.putAll(map2);
System.out.println("map1.putAll(map2): " + map1);
}
}
更多应用场景可参考:
https://blog.csdn.net/wwwdc1012/article/details/82945703
对于合成模式而言,在安全性和透明性上,会更看重透明性,毕竟合成模式的目的是:让客户端不再区分操作的是树枝对象还是树叶对象,而是以一个统一的方式来操作。
而且对于安全性的实现,需要区分是树枝对象还是树叶对象。有时候,需要将对象进行类型转换,却发现类型信息丢失了,只好强行转换,这种类型转换必然是不够安全的。
因此在使用合成模式的时候,建议多采用透明性的实现方式。
我是一名后端开发工程师。
主要关注后端开发,数据安全,爬虫,物联网,边缘计算等方向,欢迎交流。
公众号:后端技术漫谈.jpg
如果文章对你有帮助,不妨收藏,投币,转发,在看起来~
标签:static get 管理 代理模式 参考 ima lin Stub cad
原文地址:https://blog.51cto.com/15047490/2560662