设计模式—–迭代器模式和组合模式
个人博客,想要搭建个人博客的可以进来看看: http://www.ioqian.top/
迭代器模式 , 提供一种方法顺序访问一个集合对象中的各个元素,而又不暴露其内部的表示
组合模式 ,允许你将对象组合成树结构来表现“整体/部分”层次结构。组合可以让客户以一致的方式处理个别对象以及对象组合。
设计模式系列源码 : https://github.com/liloqian/DesiginModeDemo
1.迭代器模式
背景,在我们的code中,会使用各种各样的集合,最常用的有数组,链表等。在访问这些集合的过程中,访问的方式各不相同(数组:arr[i] —- List:list.get(i))为了是访问更加灵活,我们需要为所有的集合提供统一的访问接口,并且不暴露内部的表示。
1.1 迭代器模式UML类图
- Iterator ,迭代抽象类
- ConcreteIterator ,具体迭代器类,针对不同的集合种类有不同的实现
- Aggregate , 集合抽象类 , 每种集合都要继承的接口
- ConcreteAggregate , 具体的集合类
从上面我们可以发现,Client不需要和具体的集合交互,仅仅和迭代器接口和集合接口交互;迭代器负责访问数据,和集合的实现分开,使得责任各得其所;
1.2 代码
Iterator迭代抽象类
public interface Iterator {
boolean hasNext(); //是否存在下一个元素
Object next(); //返回下一个元素
void remove(); //移除元素
}
Aggregate 集合抽象类
public interface Aggregate {
Iterator createIterator(); //每个集合都要可以用迭代器遍历
}
ConcreteAggregate 具体集合类
public class ArrayCollections implements Aggregate{
//数据使用数组存储
Person[] arrays = new Person[5];
public ArrayCollections() {
for (int i = 0; i < arrays.length; i++) {
arrays[i] = new Person("Array"+i,i*i);
}
}
@Override
public Iterator createIterator() {
return new ArrayLiterator(arrays);
}
}
public class ListCollections implements Aggregate{
//使用List存储数据
List<Person> lists = new ArrayList<>();
public ListCollections(){
for(int i = 0 ; i < 5;i++){
lists.add(new Person("List"+i,i*i));
}
}
@Override
public Iterator createIterator() {
return new ListIterator(lists);
}
}
ConcreteIterator 具体迭代器
public class ArrayLiterator implements Iterator {
Person[] arrays;
int position = 0;
public ArrayLiterator(Person[] persons) {
this.arrays = persons;
}
@Override
public boolean hasNext() {
if(position >= arrays.length || arrays[position] == null){
return false;
}else {
return true;
}
}
@Override
public Object next() {
Person person = arrays[position];
position += 1;
return person;
}
@Override
public void remove() {
throw new UnsupportedOperationException("暂不支持");
}
}
public class ListIterator implements Iterator {
List<Person> list;
int position = 0;
public ListIterator(List<Person> list) {
this.list = list;
}
@Override
public boolean hasNext() {
if(position >= list.size() || list.get(position)==null){
return false;
}else {
return true;
}
}
@Override
public Object next() {
Person person = list.get(position);
position += 1;
return person;
}
@Override
public void remove() {
throw new UnsupportedOperationException("暂不支持");
}
}
测试Main
public class Main {
public static void main(String[] args) {
//使用抽象集合类
Aggregate arrays = new ArrayCollections();
Aggregate lists = new ListCollections();
Iterator arrIterator = arrays.createIterator();
Iterator listIterator = lists.createIterator();
//可以看到两种集合的访问都是一样的,我们不知道内部细节
printInfo(arrIterator);
System.out.println("-----------分割线------------");
printInfo(listIterator);
}
private static void printInfo(Iterator iterator) {
while (iterator.hasNext() ){
System.out.println(iterator.next());
}
}
}
//结果:
Person{name='Array0', age=0}
Person{name='Array1', age=1}
Person{name='Array2', age=4}
Person{name='Array3', age=9}
Person{name='Array4', age=16}
-----------分割线------------
Person{name='List0', age=0}
Person{name='List1', age=1}
Person{name='List2', age=4}
Person{name='List3', age=9}
Person{name='List4', age=16}
Process finished with exit code 0
2 设计原则 单一责任
单一责任,一个类应该只有一个引起变化的原因。
内聚是用来度量一个类或者模块紧密地到达单一目的或责任。当一个模块或者类被设计成只支持一组相关的功能时,我们说它具有高内聚;反之,说它具有低内聚。
3.组合模式
组合模式,又叫部分整体模式。是为了忽略单个对象和对象集合的区别,统一使用组合结构中的所以对象(包括集合和对象)
3.1组合模式UML类图
背景 我们要出去旅游,需要有组织有纪律,人太多不好管理所以需要分成一个个组织(一个组织可能一个人或多个人),有的队都有几个组织。博主这里描述不清楚了…..
- Component , 为组合中的所有对象声明一个接口,不管是组合还是叶节点 ,背景中的组织
- Leaf , 叶节点 ,组织只有一个人
- Composite,有叶节点的操作和组合对象的操作 ,组织有好几个组织
Leaf和Composite的关系可以参考下图,类似UI树的,集合的成员可以是集合
3.2代码实现,模拟上图中的组合
Compoent
/**抽象父类*/
public abstract class PersonFather {
//这里直接抛出异常是因为printInfo()方法所以继承者都要重写,不论leaf还是Composite
public void printInfo(){
throw new UnsupportedOperationException();
}
//下面这两个方法只有Composite必须实现,所以在leaf中调用会出现运行时异常提醒
public void add(PersonFather element){
throw new UnsupportedOperationException();
}
void remvoe(PersonFather p){
throw new UnsupportedOperationException();
}
}
Leaf
public class PersonSelf extends PersonFather {
//两个变量模拟对象状态
String name;
int gae;
public PersonSelf(String name, int gae) {
this.name = name;
this.gae = gae;
}
//实现打印状态信息
@Override
public void printInfo() {
System.out.println(this.toString());
}
@Override
public String toString() {
return "PersonSelf{" +
"name='" + name + '\'' +
", gae=" + gae +
'}';
}
}
Composite
public class PesonGroup extends PersonFather {
//存储子类的集合
List<PersonFather> lists = new ArrayList<>();
String name;
String age;
public PesonGroup(String name, String age) {
this.name = name;
this.age = age;
}
@Override
public void add(PersonFather element) {
lists.add(element);
}
@Override
void remvoe(PersonFather p) {
lists.remove(p);
}
@Override
public void printInfo() {
System.out.println(this.toString());
System.out.println("--------打印组织成员信息 start------");
Iterator iterator = lists.iterator();
//迭代递归打印
while (iterator.hasNext()){
PersonFather peson = (PersonFather) iterator.next();
peson.printInfo();
}
System.out.println("----------------------- end-------");
}
@Override
public String toString() {
return "PesonGroup{" +
"lists=" + lists +
", name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
测试Main
public class Main {
public static void main(String[] args) {
//root根节点
PersonFather root = new PesonGroup("root",0+"");
//2个leaf节点,root儿子
PersonFather son1 = new PersonSelf("son1",1);
PersonFather son2 = new PersonSelf("son2",2);
//1个group节点,是root的儿子
PersonFather Songroup3 = new PesonGroup("sonGroup3" , 3 + "");
//root把儿子挂在自己下面
root.add(son1);
root.add(son2);
root.add(Songroup3);
//root的三儿子group节点由有4个儿子,root的4个孙子
Songroup3.add(new PersonSelf("grandson1",1));
Songroup3.add(new PersonSelf("grandson2",2));
Songroup3.add(new PersonSelf("grandson3",3));
Songroup3.add(new PersonSelf("grandson4",4));
//打印root家族信息
root.printInfo();
System.out.println("******************我是分割线*********************");
//打印root三儿子家族信息
Songroup3.printInfo();
System.out.println("******************我是分割线*********************");
//打印root大儿子信息,就一个单身狗
son1.printInfo();
}
}
//结果:
PesonGroup{lists=[PersonSelf{name='son1', gae=1}, PersonSelf{name='son2', gae=2}, PesonGroup{lists=[PersonSelf{name='grandson1', gae=1}, PersonSelf{name='grandson2', gae=2}, PersonSelf{name='grandson3', gae=3}, PersonSelf{name='grandson4', gae=4}], name='sonGroup3', age='3'}], name='root', age='0'}
--------打印组织成员信息 start------
PersonSelf{name='son1', gae=1}
PersonSelf{name='son2', gae=2}
PesonGroup{lists=[PersonSelf{name='grandson1', gae=1}, PersonSelf{name='grandson2', gae=2}, PersonSelf{name='grandson3', gae=3}, PersonSelf{name='grandson4', gae=4}], name='sonGroup3', age='3'}
--------打印组织成员信息 start------
PersonSelf{name='grandson1', gae=1}
PersonSelf{name='grandson2', gae=2}
PersonSelf{name='grandson3', gae=3}
PersonSelf{name='grandson4', gae=4}
----------------------- end-------
----------------------- end-------
******************我是分割线*********************
PesonGroup{lists=[PersonSelf{name='grandson1', gae=1}, PersonSelf{name='grandson2', gae=2}, PersonSelf{name='grandson3', gae=3}, PersonSelf{name='grandson4', gae=4}], name='sonGroup3', age='3'}
--------打印组织成员信息 start------
PersonSelf{name='grandson1', gae=1}
PersonSelf{name='grandson2', gae=2}
PersonSelf{name='grandson3', gae=3}
PersonSelf{name='grandson4', gae=4}
----------------------- end-------
******************我是分割线*********************
PersonSelf{name='son1', gae=1}
Process finished with exit code 0
3.3 组合模式总结
- 整体/部分思想,包含其他组件的组件称为组合对象,没有包含其他组件的组件称为叶节点对象
- 调用组合对象或者叶节点对象的方式一致,如果一些方法对叶节点没有意义可以空实现,也可以和代码中的一样直接抛出异常