北京建设部网站首页,wordpress 育儿主题,地方门户网站系统,wordpress评论提示1、目标
本文的主要目标是学习创建型模式和结构型模式#xff0c;并分别代码实现每种设计模式
2、创建型模式
2.1 单例模式#xff08;singleton#xff09;
单例模式是创建一个对象保证只有这个类的唯一实例#xff0c;单例模式分为饿汉式和懒汉式#xff0c;饿汉式是…1、目标
本文的主要目标是学习创建型模式和结构型模式并分别代码实现每种设计模式
2、创建型模式
2.1 单例模式singleton
单例模式是创建一个对象保证只有这个类的唯一实例单例模式分为饿汉式和懒汉式饿汉式是类加载的时候就创建这个类的唯一对象懒汉式是获取这个类的对象时才会创建对象
程序
public class SingletonFactory {// 饿汉式的单例模式public static class Singleton01 {private static final Singleton01 INSTANCE new Singleton01();// 构造器私有化private Singleton01() {}public static Singleton01 getInstance() {return INSTANCE;}}// 懒汉式的单例模式不加锁推荐public static class Singleton02 {// 使用静态内部类封装单例对象实现懒加载也可以保证线程安全private static class Singleton02Holder {private static final Singleton02 INSTANCE new Singleton02();}// 构造器私有化private Singleton02() {}public static Singleton02 getInstance() {return Singleton02Holder.INSTANCE;}}// 懒汉式的单例模式加锁双端检查public static class Singleton03 {// 不会初始化INSTANCE必须加上volatile保证可见性和禁止指令重排序// volatile的作用// 1、保证可见性修改INSTANCE变量会立即更新到主内存中其他线程读取INSTANCE变量会从主内存中读取数据保证实例的唯一性// 2、禁止指令重排序必须先初始化INSTANCE对象然后对象空间赋值给INSTANCE变量保证实例的完整性private static volatile Singleton03 INSTANCE;// 构造器私有化private Singleton03() {}public static Singleton03 getInstance() {if(INSTANCE ! null) {return INSTANCE;}synchronized (Singleton03.class) {if(INSTANCE null) {INSTANCE new Singleton03();}}return INSTANCE;}}}volatile的作用 1、保证可见性修改INSTANCE变量会立即更新到主内存中其他线程读取INSTANCE变量会从主内存中读取数据保证实例的唯一性 2、禁止指令重排序必须先初始化INSTANCE对象然后对象空间赋值给INSTANCE变量保证实例的完整性 volatile是禁止指令重排序因为对象创建的顺序是 ① 在堆中创建对象空间 ② 属性默认初始化、构造器初始化 ③ 将堆中的对象空间指向栈中的对象引用如果没有volatile可能会重排序先将堆中的对象空间指向栈中的对象引用此时另一个线程发现对象创建了就直接返回但此时这个对象还没有属性默认初始化、构造器初始化是一个不完整的对象 构造器私有化 双端检测double check lock第一个if判断是否是单例对象是否为空是因为已经创建单例对象了就不会获取锁第二个if判断是否是单例对象是因为多个线程并发获取锁获取锁失败的要进来再次初始化所以用if判断就不用再次初始化了
public class TaskController {Testpublic void f5() {SingletonFactory.Singleton01 singleton01 SingletonFactory.Singleton01.getInstance();System.out.println(singleton01 singleton01);singleton01 SingletonFactory.Singleton01.getInstance();System.out.println(singleton01 singleton01);System.out.println();SingletonFactory.Singleton02 singleton02 SingletonFactory.Singleton02.getInstance();System.out.println(singleton02 singleton02);singleton02 SingletonFactory.Singleton02.getInstance();System.out.println(singleton02 singleton02);System.out.println();SingletonFactory.Singleton03 singleton03 SingletonFactory.Singleton03.getInstance();System.out.println(singleton03 singleton03);singleton03 SingletonFactory.Singleton03.getInstance();System.out.println(singleton03 singleton03);}
}多次获取同一个类的单例对象
测试结果
获取的是同一个对象
2.2 原型模式prototype
原型模式是通过拷贝对象来创建新的对象定义一个抽象类可以定义clone抽象方法子类重写这个clone方法
程序
public class JobFactory {abstract public class Job {private String name;public Job(String name) {this.name name;}public String getName() {return name;}abstract public Job clone();}public class Stu extends Job {public Stu() {super(学生);}Overridepublic Job clone() {return new Stu();}}public class Teacher extends Job {public Teacher() {super(老师);}Overridepublic Job clone() {return new Teacher();}}}定义一个抽象类定义clone抽象方法子类重写clone抽象方法
public class TaskController {Testpublic void f6() {JobFactory jobFactory new JobFactory();JobFactory.Job job jobFactory.new Stu();System.out.println(job job);job job.clone();System.out.println(job job);System.out.println();job jobFactory.new Teacher();System.out.println(job job);job job.clone();System.out.println(job job);}
}通过clone方法可以实现原型模式通过拷贝对象来创建一个新的对象
测试结果 原型模式可以创建一个新的对象
2.3 建造者模式Builder
建造者模式是将复杂对象的构建过程和表示分离开来因此同样的构建过程可以创建不同的表示即不同的属性值
程序
public class SkillBuilder {private Skill skill new Skill();public SkillBuilder buildFront(String name) {skill.setFront(name);return this;}public SkillBuilder buildBack(String name) {skill.setBack(name);return this;}public SkillBuilder buildTest(String name) {skill.setTest(name);return this;}public SkillBuilder buildUe(String name) {skill.setUe(name);return this;}public Skill getSkill() {return skill;}public class Skill {private String front;private String back;private String test;private String ue;public void setFront(String front) {this.front front;}public void setBack(String back) {this.back back;}public void setTest(String test) {this.test test;}public void setUe(String ue) {this.ue ue;}Overridepublic String toString() {return Skill{ front front \ , back back \ , test test \ , ue ue \ };}}}创建一个Builder类封装Skill对象属性的构建过程并可以实现链式调用
public class TaskController {Testpublic void f7() {SkillBuilder skillBuilder new SkillBuilder();SkillBuilder.Skill skill skillBuilder.buildFront(前端).buildBack(后端).buildTest(测试).buildUe(UE).getSkill();System.out.println(skill skill);}
}通过SkillBuilder可以创建Skill对象并且是链式调用
测试结果 通过建造者模式可以创建一个对象
2.4 工厂方法模式Factory Method
工厂方法模式是根据不同的条件创建不同类型的对象优点是可以通过工厂类创建不同类型的对象耦合性小
需求根据不同类型创建不同的形状 分析不同的类型用if else判断硬编码
优化思路设计一个工厂类根据不同类型创建不同的对象也可以将对象放到map中然后map.get获取不同类型的对象
程序
public class ShapeFactory {private MapString, Shape map new HashMap();public ShapeFactory() {map.put(rectangle, new Rectangle());map.put(circle, new Circle());}public Shape addShapeByType(String type) {// 根据map查询返回的类型也可以直接用if else判断类型然后new一个新的对象并返回return map.get(type);}public abstract class Shape {abstract public void draw();}public class Rectangle extends Shape {Overridepublic void draw() {System.out.println(长方形);}}public class Circle extends Shape {Overridepublic void draw() {System.out.println(圆形);}}}工厂类设计一个map将所有的形状都放到map中然后map.get就可以获取不同类型的形状
public class TaskController {Testpublic void f4() {ShapeFactory shapeFactory new ShapeFactory();ShapeFactory.Shape shape shapeFactory.addShapeByType(rectangle);System.out.println(shape shape);shape.draw();System.out.println();shape shapeFactory.addShapeByType(circle);System.out.println(shape shape);shape.draw();}
}入参是形状类型会返回一个指定类型的形状
测试结果 测试结果是可以根据不同的类型创建不同类型的对象
2.5 抽象工厂模式Abstract Factory
抽象工厂模式可以创建多组相关的对象一组中包含多个对象定义一个抽象类指定创建一组对象多个实现类创建多组对象抽象工厂模式可以将使用哪些对象和如何使用这些对象的操作分离开来优点用来返回一组对象耦合性小增加一组对象会很清晰
需求根据计算机分辨率大小创建返回显示和打印形状的驱动程序 分析 ① 显示形状的驱动程序有LRDD、MRDD、HRDD打印形状的驱动程序有LRPD、MRPD、HRPD其中L开头的是低分辨率的M开头的是中分辨率的H开头的是高分辨率的因此将驱动程序分成两类DisplayDriver、PrintDriver ② 对于不同类型的分辨率可以用if条件判断但是如果增加一个类型的分辨率会耦合性高
优化思路设计抽象类是分辨率Resolution这个抽象类中指定创建DisplayDriver对象和PrintDriver对象等这一组对象为抽象类的一组对象可以创建多个实现类即计算机分辨率有低、中、高分辨率分别是LowResolution、MiddleResolution、HighResolutionTestController类调用这些类得到一组对象进行操作因此将使用哪些对象和如何使用这些对象的操作分离开来
程序
public class ResolutionFactory {// 抽象工厂类Resolution定义一组对象多个实现类创建多组对象public abstract class Resolution {abstract public DisplayDriver getDisplayDriver();abstract public PrintDriver getPrintDriver();}public class LowResolution extends Resolution {Overridepublic DisplayDriver getDisplayDriver() {return new DisplayDriver(LRDD);}Overridepublic PrintDriver getPrintDriver() {return new PrintDriver(LRPD);}}public class MiddleResolution extends Resolution {Overridepublic DisplayDriver getDisplayDriver() {return new DisplayDriver(MRDD);}Overridepublic PrintDriver getPrintDriver() {return new PrintDriver(MRPD);}}public class HighResolution extends Resolution {Overridepublic DisplayDriver getDisplayDriver() {return new DisplayDriver(HRDD);}Overridepublic PrintDriver getPrintDriver() {return new PrintDriver(HRPD);}}public class DisplayDriver {private String name;public DisplayDriver(String name) {this.name name;}Overridepublic String toString() {return DisplayDriver{ name name \ };}}public class PrintDriver {private String name;public PrintDriver(String name) {this.name name;}Overridepublic String toString() {return PrintDriver{ name name \ };}}}抽象工厂类Resolution定义一组对象多个实现类创建多组对象一组对象中包含DisplayDriver、PrintDriver
import org.junit.jupiter.api.Test;public class TaskController {Testpublic void f3() {ResolutionFactory resolutionFactory new ResolutionFactory();ResolutionFactory.LowResolution lowResolution resolutionFactory.new LowResolution();ResolutionFactory.DisplayDriver displayDriver lowResolution.getDisplayDriver();ResolutionFactory.PrintDriver printDriver lowResolution.getPrintDriver();System.out.println(LowResolution: displayDriver displayDriver , printDriver printDriver);ResolutionFactory.MiddleResolution middleResolution resolutionFactory.new MiddleResolution();displayDriver middleResolution.getDisplayDriver();printDriver middleResolution.getPrintDriver();System.out.println(MiddleResolution: displayDriver displayDriver , printDriver printDriver);ResolutionFactory.HighResolution highResolution resolutionFactory.new HighResolution();displayDriver highResolution.getDisplayDriver();printDriver highResolution.getPrintDriver();System.out.println(HighResolution: displayDriver displayDriver , printDriver printDriver);}
}TaskController通过getDisplayDriver方法和getPrintDriver方法得到显示驱动程序和打印驱动程序
测试结果是 为了得到显示驱动程序和打印驱动程序这一组对象设置一个抽象类分辨率和多个分辨率实现类可以创建多组相关的对象
3、结构型模式
3.1 外观模式Facade
外观模式是为复杂系统提高一个新的接口作用是可以简化复杂系统的使用或者只使用复杂系统的一部分功能可以封装系统功能因此用外观模式
程序
public class ComputerFactory {public class Computer {private Cpu cpu;private Memory memory;private Disk disk;public Computer(Cpu cpu, Memory memory, Disk disk) {this.cpu cpu;this.memory memory;this.disk disk;}public void start() {cpu.start();memory.start();disk.start();System.out.println(Computer started ok);}public void end() {cpu.end();memory.end();disk.end();System.out.println(Computer ended ok);}}public class Cpu {public void start() {System.out.println(Cpu started);}public void end() {System.out.println(Cpu ended);}}public class Memory {public void start() {System.out.println(Memory started);}public void end() {System.out.println(Memory ended);}}public class Disk {public void start() {System.out.println(Disk started);}public void end() {System.out.println(Disk ended);}}}开启电脑会启动Cpu、Memory、Disk等组件因此外观模式相当于封装了电脑的各个组件的启动过程
public class TaskController {Testpublic void f9() {ComputerFactory computerFactory new ComputerFactory();ComputerFactory.Cpu cpu computerFactory.new Cpu();ComputerFactory.Memory memory computerFactory.new Memory();ComputerFactory.Disk disk computerFactory.new Disk();ComputerFactory.Computer computer computerFactory.new Computer(cpu, memory, disk);computer.start();System.out.println();computer.end();}
}测试结果 外观模式可以封装一个复杂对象的启动过程
3.2 适配器模式Adapter
适配器模式是将一个接口转换成另一个接口作用是保证接口是兼容的保证多态
程序
public class Shape02Factory {abstract public class Shape {private String name;public Shape(String name) {this.name name;}public String getName() {return name;}public void setName(String name) {this.name name;}abstract public void show();}public class Circle extends Shape {// 适配器模式是组合另一个类private final XXCircle xxCircle;public Circle(String name, XXCircle xxCircle) {super(name);this.xxCircle xxCircle;}Overridepublic void show() {xxCircle.display();}}public class XXCircle {public void display() {System.out.println(XXCircle display圆形);}}
}Circle继承了Shape抽象类重写了display方法Circle类组合了XXCircle对象用来调用它的displayIt方法可以保证多态
public class TaskController {Testpublic void f8() {Shape02Factory shape02Factory new Shape02Factory();Shape02Factory.XXCircle xxCircle shape02Factory.new XXCircle();Shape02Factory.Circle circle shape02Factory.new Circle(圆形, xxCircle);circle.show();}
}测试结果 适配器模式会调用另一个类的方法
3.3 桥接模式Bridge
桥接模式是将抽象和实现解耦使它们都能独立的变化寻找可变的参数并封装到一个类中拆分出抽象和实现实现作为抽象的一个属性即用组合代替继承如果每个抽象都调用具体的实现会出现抽象和实现耦合并且类很多因此实现也需要抽象出一个抽象类或者接口每个抽象只需要调用实现的抽象类即可比如这里的抽象指的是形状实现指的是画出这个形状需要的画线或者画圆方法优点抽象和实现解耦耦合性小增加一个抽象或者实现会很清晰
需求画某个形状的图比如长方形或者圆形用多个画图程序包括画线、画圆实现画某个形状的图的功能
分析 假设现在有多个形状有多个程序都可以实现每个形状的绘制功能如果每个形状都创建多个类用来调用多个程序的绘制功能或者每个形状都组合多个程序类来绘制同一个形状这样会造成类或者组合数量多并且耦合性高
优化思路 寻找可变的参数并封装到一个类中拆分出抽象和实现将多个实现封装在一个抽象类中然后用组合替代继承将实现的抽象类组合在抽象中 这里抽象出Shape抽象类和Drawing抽象类Shape抽象类作为抽象Drawing抽象类作为实现
程序
public class ShapeFactory {public void process(Shape shape) {shape.draw();}// 形状抽象类是抽象public abstract class Shape {abstract public void draw();}public class Rectangle extends Shape {private int x1, y1, x2, y2;private Drawing drawing;public Rectangle(int x1, int y1, int x2, int y2, Drawing drawing) {this.x1 x1;this.y1 y1;this.x2 x2;this.y2 y2;this.drawing drawing;}Overridepublic void draw() {// Rectangle组合了Drawing实现避免分别调用V1Drawing和V2Drawing的drawLine方法drawing.drawLine(x1, y1, x1, y2);drawing.drawLine(x1, y2, x2, y2);drawing.drawLine(x2, y2, x2, y1);drawing.drawLine(x2, y1, x1, y1);}}public class Circle extends Shape {private int x, y, r;private Drawing drawing;public Circle(int x, int y, int r, Drawing drawing) {this.x x;this.y y;this.r r;this.drawing drawing;}Overridepublic void draw() {// Circle组合了Drawing实现避免分别调用V1Drawing和V2Drawing的drawCircle方法drawing.drawCircle(x, y, r);}}// 多个绘图程序抽象出绘图抽象类绘图抽象类就是形状抽象的实现public abstract class Drawing {public abstract void drawLine(int x1, int y1, int x2, int y2);public abstract void drawCircle(int x, int y, int r);}public class V1Drawing extends Drawing {Overridepublic void drawLine(int x1, int y1, int x2, int y2) {System.out.println(使用绘图程序 1 绘制线条line: x1 x1 y1 y1 x2 x2 y2 y2);}Overridepublic void drawCircle(int x, int y, int r) {System.out.println(使用绘图程序 1 绘制圆circle: x x y y r r);}}public class V2Drawing extends Drawing {Overridepublic void drawLine(int x1, int y1, int x2, int y2) {System.out.println(使用绘图程序 2 绘制线条line: x1 x1 y1 y1 x2 x2 y2 y2);}Overridepublic void drawCircle(int x, int y, int r) {System.out.println(使用绘图程序 2 绘制圆circle: x x y y r r);}}}ShapeFactory类封装了process方法可以调用形状Shape抽象类的draw方法实现用Drawing抽象类来表示
其中画长方形这个形状的draw方法调用了4个drawLine方法 长方形画图程序有4个点可以只记录x1,y1,x2,y2这4个参数即可画4条线4条线的起始点和终止点分别是(x1,y1)和(x1,y2)、(x1,y2)和(x2,y2)、(x2,y2)和(x2,y1)、(x2,y1)和(x1,y1)
优点增加一个画图方法或者一个形状修改的话会很清晰
import org.junit.jupiter.api.Test;public class TaskController {Testpublic void f2() {ShapeFactory shapeFactory new ShapeFactory();ShapeFactory.Drawing drawing shapeFactory.new V1Drawing();ShapeFactory.Shape shape shapeFactory.new Rectangle(1,2, 4,6, drawing);shapeFactory.process(shape);System.out.println();drawing shapeFactory.new V2Drawing();shape shapeFactory.new Rectangle(1, 2, 4, 6, drawing);shapeFactory.process(shape);System.out.println();drawing shapeFactory.new V1Drawing();shape shapeFactory.new Circle(1,3, 2, drawing);shapeFactory.process(shape);System.out.println();drawing shapeFactory.new V2Drawing();shape shapeFactory.new Circle(1, 3, 2, drawing);shapeFactory.process(shape);}
}测试方法会先创建ShapeFactory对象然后创建Drawing实现接着创建Shape抽象因为已经将Drawing实现组合到Shape抽象因此Shape抽象调用Drawing实现即可最后调用ShapeFactory对象的process方法执行画图功能
测试结果 分别用绘图程序1和2绘制线条line和圆circle
3.4 装饰器模式Decorator
装饰器模式可以在对象的之前或者之后动态添加功能动态调整顺序不用创建子类就可以动态扩展功能创建一个对象链实现动态添加功能的效果如何实现这种链式调用呢创建一个装饰器抽象类它包含Component对象包含的show方法会调用Component对象的show方法由于java的多态是动态绑定机制因此会调用运行类型对象的show方法从而实现Component的多个实现类对象的链式调用优点装饰器模式可以在对象的之前或者之后动态添加功能不用创建子类就可以动态扩展功能扩展性强Java的IO流广泛使用了装饰器模式
需求为销售票据添加表头、页脚等信息 分析 创建票据对象创建子类直接在方法开头加上表头在方法结尾加上页脚这是硬编码如果有多个表头和页脚那怎么办只能创建多个子类即硬编码
优化思路 采用装饰器模式创建一个对象链这个对象链起始于装饰器Decorator对象终止于原始对象对象链可以在对象之前或者之后动态添加功能
程序
public class ComponentFactory {public void show(Component component) {component.show();}abstract public class Component {abstract public void show();}// 原始对象票据对象SaleTicketpublic class SaleTicket extends Component {Overridepublic void show() {System.out.println(销售票据SaleTicket);}}// 装饰器抽象类组合了Component对象可以调用component的show方法实现链式调用不用创建子类就可以动态扩展功能abstract public class TicketDecorator extends Component {private Component component;public TicketDecorator(Component component) {this.component component;}Overridepublic void show() {// 运行类型子类调用show方法component.show();}}public class Header extends TicketDecorator {private String msg;public Header(Component component, String msg) {super(component);this.msg msg;}Overridepublic void show() {System.out.println(Header: msg);// 调用父类的show方法super.show();}}public class Footer extends TicketDecorator {private String msg;public Footer(Component component, String msg) {super(component);this.msg msg;}Overridepublic void show() {// 调用父类的show方法super.show();System.out.println(Footer: msg);}}}创建Component抽象类创建票据对象SaleTicket要在这个对象的之前或者之后添加功能因此SaleTicket对象是原始对象用装饰器模式创建装饰器抽象类TicketDecorator它组合了Component对象它包含的show方法可以调用Component对象的show方法实现链式调用因为java的多态是动态绑定机制因此会调用运行类型对象的show方法装饰器模式的好处是不用创建子类就可以动态扩展功能
public class TaskController {Testpublic void f1() {ComponentFactory componentFactory new ComponentFactory();ComponentFactory.SaleTicket saleTicket componentFactory.new SaleTicket();ComponentFactory.Footer footer componentFactory.new Footer(saleTicket, 部门yyy);footer componentFactory.new Footer(footer, 页号1);ComponentFactory.Header header componentFactory.new Header(footer, 申请人zzz);header componentFactory.new Header(header, 公司xxx);componentFactory.show(header);}
}先创建ComponentFactory工厂类对象然后创建原始对象SaleTicket对象接着创建Footer对象并将SaleTicket对象组合到其中然后创建Header对象并将Footer对象组合到其中最后调用ComponentFactory工厂类对象的show方法会链式调用Component对象的show方法
测试结果 测试结果是原始对象销售票据之前添加了两个头部之后添加了两个页脚可以动态扩展功能
3.5 享元模式Flyweight
享元模式是共享的对象只会创建1次避免创建大量相似的对象思路是创建一个享元工厂就是一个map获取对象的时候会判断如果对象不存在就创建对象并添加到map中如果对象存在就不用创建对象了直接从map获取
程序
public class CheseFactory {private MapString, Chese map new HashMap();public Chese getChese(String color) {if(map.containsKey(color)) {return map.get(color);}Chese chese new Chese(color);map.put(color, chese);return chese;}public class Chese {private String color;public Chese(String color) {this.color color;}public String getColor() {return color;}public void setColor(String color) {this.color color;}}}有多个棋子如果颜色相同不用重复创建用享元模式创建一个对象会放到map中
public class TaskController {Testpublic void f10() {CheseFactory cheseFactory new CheseFactory();CheseFactory.Chese chese cheseFactory.getChese(red);System.out.println(chese chese);chese cheseFactory.getChese(blue);System.out.println(chese chese);chese cheseFactory.getChese(red);System.out.println(chese chese);chese cheseFactory.getChese(blue);System.out.println(chese chese);}
}通过getChese方法传入参数是颜色
测试结果 通过getChese方法传入参数如果map中已经存在这个颜色的棋子就会直接返回不会重复创建避免创建大量重复对象
3.6 代理模式Proxy
代理模式是不改变原始对象的情况下对功能的增强这样可以保证原始对象的单一职责原则思路是创建一个代理对象代理对象中持有了原始对象的引用
程序
public class SportsFactory {public interface Sports {public void doSports();}public class SportsImpl implements Sports {Overridepublic void doSports() {System.out.println(doSports ing~);}}public class JDKInvocationHandler implements InvocationHandler {private Object target;public JDKInvocationHandler(Object target) {this.target target;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(before doSports: buy water);Object res method.invoke(target, args);System.out.println(after doSports: take a shower);return res;}public Object getProxy() {return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}}}创建一个接口创建一个实现类创建一个JDK动态代理对象实现InvocationHandler接口重写invoke方法用Proxy.newProxyInstance方法创建基于接口的JDK动态代理对象
Test
public void f12() {SportsFactory sportsFactory new SportsFactory();SportsFactory.Sports sports sportsFactory.new SportsImpl();SportsFactory.JDKInvocationHandler jdkInvocationHandler sportsFactory.new JDKInvocationHandler(sports);// 创建JDK动态代理对象sports (SportsFactory.Sports) jdkInvocationHandler.getProxy();sports.doSports();
}创建基于接口的JDK动态代理对象JDK代理对象和实现类对象是兄弟的关系因为它们都实现了同一个接口
测试结果 JDK动态代理可以在实现类的方法之前和之后分别输出这是为了保证设计模式中一个类的单一职责原则
3.7 组合模式Composite
组合模式是将对象组合成树状结构表示树状的层次关系思路是创建一个抽象类创建目录和文件目录中可以包含文件或者子目录因此目录这个类中包含一个List集合
程序
public class CompositeFactory {abstract public class Component {private String name;public Component(String name) {this.name name;}abstract public void addComponent(Component component);abstract public void show();}public class File extends Component {public File(String name) {super(name);}Overridepublic void addComponent(Component component) {throw new RuntimeException(文件不能添加子元素);}Overridepublic void show() {System.out.println(File name super.name);}Overridepublic String toString() {return { File name super.name } ;}}public class Dict extends Component {private ListComponent list new ArrayList();public Dict(String name) {super(name);}Overridepublic void addComponent(Component component) {list.add(component);}Overridepublic void show() {// 将list集合中的Component对象转成String字符串并按照逗号分隔String s list.stream().map(component - component.toString()).collect(Collectors.joining(,));System.out.println(Dict name super.name 它包含了list s);}Overridepublic String toString() {return { Dict name super.name , list list.toString() } ;}}}创建一个抽象类创建文件和目录目录中可以存放子目录和文件因此用一个List集合存放它们
Test
public void f11() {CompositeFactory compositeFactory new CompositeFactory();CompositeFactory.File file01 compositeFactory.new File(file01);CompositeFactory.File file02 compositeFactory.new File(file02);CompositeFactory.File file03 compositeFactory.new File(file03);CompositeFactory.File file04 compositeFactory.new File(file04);CompositeFactory.Dict dict01 compositeFactory.new Dict(dict01);CompositeFactory.Dict dict02 compositeFactory.new Dict(dict02);CompositeFactory.Dict dict03 compositeFactory.new Dict(dict03);dict01.addComponent(dict02);dict01.addComponent(dict03);dict02.addComponent(file01);dict02.addComponent(file02);dict03.addComponent(file03);dict03.addComponent(file04);dict01.show();
}创建树状结构
测试结果 组合模式可以展示树状结构