JAVA 设计模式之组合模式
文章目录
1. 定义
将对象组合成树形结构已表示”部分-整体“的层次结构
组合模式使客户端对单个对象和组合对象保持一致的处理方式
2. 类型
结构型
3 适用场景
希望客户端可以忽略组合对象与单个对象的差异时
处理一个树形结构时
4. 优点
- 清晰的定义分层次的复杂对象,表示对象的全部或部分层次
- 让客户端忽略的了层次的差异,方便对整个层次结构进行控制
- 简化客户端代码
- 符合开闭原则
5. 缺点
- 限制类型时较为复杂
- 使设计变得更加抽象
6. 组合模式的相关设计模式
组合模式和访问模式
访问模式可以访问组合模式的递归结构
7. coding
7.1 目录接口
public abstract class CatalogComponent {
public void add(CatalogComponent catalogComponent){
throw new UnsupportedOperationException("不支持添加操作");
}
public void remove(CatalogComponent catalogComponent){
throw new UnsupportedOperationException("不支持删除操作");
}
public String getName(CatalogComponent catalogComponent){
throw new UnsupportedOperationException("不支持获取名称操作");
}
public double getPrice(CatalogComponent catalogComponent){
throw new UnsupportedOperationException("不支持获取价格操作");
}
public void print(){
throw new UnsupportedOperationException("不支持打印操作");
}
}
7.2 课程继承目录接口
public class Course extends CatalogComponent {
private String name;
private double price;
public Course(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String getName(CatalogComponent catalogComponent) {
return this.name;
}
@Override
public double getPrice(CatalogComponent catalogComponent) {
return this.price;
}
@Override
public void print() {
System.out.println("Course Name:"+name+" Price:"+price);
}
}
7.3 课程目录继承目录接口
public class CourseCatalog extends CatalogComponent {
private List<CatalogComponent> items = new ArrayList<CatalogComponent>();
private String name;
private Integer level;
public CourseCatalog(String name,Integer level) {
this.name = name;
this.level = level;
}
@Override
public void add(CatalogComponent catalogComponent) {
items.add(catalogComponent);
}
@Override
public String getName(CatalogComponent catalogComponent) {
return this.name;
}
@Override
public void remove(CatalogComponent catalogComponent) {
items.remove(catalogComponent);
}
@Override
public void print() {
System.out.println(this.name);
for(CatalogComponent catalogComponent : items){
if(this.level != null){
for(int i = 0; i < this.level; i++){
System.out.print(" ");
}
}
catalogComponent.print();
}
}
}
7.4 UML
7.5 测试类
public class Test {
public static void main(String[] args) {
CatalogComponent linuxCourse = new Course("Linux课程",11);
CatalogComponent windowsCourse = new Course("Windows课程",11);
CatalogComponent javaCourseCatalog = new CourseCatalog("Java课程目录",2);
CatalogComponent mmallCourse1 = new Course("Java电商一期",55);
CatalogComponent mmallCourse2 = new Course("Java电商二期",66);
CatalogComponent designPattern = new Course("Java设计模式",77);
javaCourseCatalog.add(mmallCourse1);
javaCourseCatalog.add(mmallCourse2);
javaCourseCatalog.add(designPattern);
CatalogComponent imoocMainCourseCatalog = new CourseCatalog("慕课网课程主目录",1);
imoocMainCourseCatalog.add(linuxCourse);
imoocMainCourseCatalog.add(windowsCourse);
imoocMainCourseCatalog.add(javaCourseCatalog);
imoocMainCourseCatalog.print();
}
}
8 源码解析
8.1 Container
8.1.1. 来源
java.awt.Container
8.1.2. coding
public Component add(Component comp) {
addImpl(comp, null, -1);
return comp;
}
protected void addImpl(Component comp, Object constraints, int index) {
synchronized (getTreeLock()) {
/* Check for correct arguments: index in bounds,
* comp cannot be one of this container's parents,
* and comp cannot be a window.
* comp and container must be on the same GraphicsDevice.
* if comp is container, all sub-components must be on
* same GraphicsDevice.
*/
GraphicsConfiguration thisGC = this.getGraphicsConfiguration();
if (index > component.size() || (index < 0 && index != -1)) {
throw new IllegalArgumentException(
"illegal component position");
}
checkAddToSelf(comp);
checkNotAWindow(comp);
if (thisGC != null) {
comp.checkGD(thisGC.getDevice().getIDstring());
}
/* Reparent the component and tidy up the tree's state. */
if (comp.parent != null) {
comp.parent.remove(comp);
if (index > component.size()) {
throw new IllegalArgumentException("illegal component position");
}
}
//index == -1 means add to the end.
if (index == -1) {
component.add(comp);
} else {
component.add(index, comp);
}
comp.parent = this;
comp.setGraphicsConfiguration(thisGC);
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
adjustDescendants(comp.countHierarchyMembers());
invalidateIfValid();
if (peer != null) {
comp.addNotify();
}
/* Notify the layout manager of the added component. */
if (layoutMgr != null) {
if (layoutMgr instanceof LayoutManager2) {
((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
} else if (constraints instanceof String) {
layoutMgr.addLayoutComponent((String)constraints, comp);
}
}
if (containerListener != null ||
(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
ContainerEvent e = new ContainerEvent(this,
ContainerEvent.COMPONENT_ADDED,
comp);
dispatchEvent(e);
}
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
this, HierarchyEvent.PARENT_CHANGED,
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
if (peer != null && layoutMgr == null && isVisible()) {
updateCursorImmediately();
}
}
}