23种设计模式中篇
结构型设计模式 ,共7种
(1)桥接模式
(2)装饰者模式
(3)组合模式
(4)适配器模式
(5)外观模式
(6)享元模式
(7)代理模式
桥接模式【jdbc采用的就是这种模式】
将抽象和实现部分的分离,更好的可扩展性,桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性
//抽象的实现类 public interface Memory { void addMemory(); } //具体的实现类 public class Memory6G implements Memory{ @Override public void addMemory() { System.out.println("安装了6G内存"); } } //具体的实现类 public class Memory8G implements Memory{ @Override public void addMemory() { System.out.println("安装了8G内存"); } } //具体部分的抽象 public abstract class Phone { protected Memory memory; public void setMemory(Memory memory) { this.memory = memory; } protected abstract void buyPhone(); } public class Huiwei extends Phone{ @Override protected void buyPhone() { System.out.println("购买华为手机"); memory.addMemory(); } } public class Xiaomi extends Phone { @Override protected void buyPhone() { System.out.println("购买小米手机"); memory.addMemory(); } } public class MainClass { public static void main(String[] args) { Phone phone = new Huiwei(); phone.setMemory(new Memory6G()); phone.buyPhone(); System.out.println("==============="); phone.setMemory(new Memory8G()); phone.buyPhone(); } }
装饰者模式【jdk中有关流的操作】
给已经存在的对象动态的添加功能
//被装饰对象基类 public abstract class Girl { String description = "no particular"; public String getDescription(){ return description; } } //具体被装饰对象 public class AmericanGirl extends Girl { public AmericanGirl() { description = "American Girl"; } } //装饰者抽象类 public abstract class GirlDecorator extends Girl { public abstract String getDescription(); } //具体装饰者 public class Science extends GirlDecorator { private Girl girl; public Science(Girl girl) { this.girl = girl; } @Override public String getDescription() { return this.girl.getDescription() + " Like Science"; } public void caltulateStuff() { System.out.println("scientific calculation!"); } } //具体装饰者 public class Art extends GirlDecorator { private Girl girl; public Art(Girl girl){ this.girl = girl; } @Override public String getDescription() { return this.girl.getDescription() + " Like Art"; } public void draw() { System.out.println("draw pictures!"); } } public class MainClass { public static void main(String[] args) { //普通美国女孩 Girl g1 = new AmericanGirl(); System.out.println(g1.getDescription()); //喜欢科学 Girl g2 = new Science(g1); System.out.println(g2.getDescription()); //喜欢艺术 Girl g3 = new Art(g2); System.out.println(g3.getDescription()); } }
组合模式
将对象组合成树形结构以表示“部分-整体”的层次结构。即对象包含对象,整体包含部分,组合模式使客户端可以使用一致的方法操作单个对象和组合对象
/** * 节点公共抽象类 */ public abstract class Node { private String name; /** * 带参数的构造方法 * @param name */ public Node(String name){ this.name = name; } /** * 获得节点信息 * @return */ public String getInfo(){ return "名称:"+name; } } /** * 叶子节点(文件) */ public class File extends Node { /** * 调用父类的构造方法 * @param name */ public File(String name) { super(name); } } /** * 分支节点(文件夹) */ public class Folder extends Node{ /** * 子集 */ private ArrayList children = new ArrayList(); /** * 带参数的构造方法 * @param name */ public Folder(String name){ super(name); } /** * 新增节点,有可能是文件也有可能是文件夹 * @param node */ public void add(Node node){ this.children.add(node); } /** * 获得子集 * * @return */ public ArrayList getChildren() { return children; } } public class MainClass { public static void main(String[] args) { //定义根节点 Folder root = new Folder("root"); //定义二级节点的文件夹 Folder imageFolder = new Folder("image-folder"); Folder documentFolder = new Folder("document-folder"); //定义二级节点的文件 File systemFile = new File("system-file.bat"); //定义三级节点的文件夹 Folder pngFolder = new Folder("png-folder"); Folder gifFolder = new Folder("gif-folder"); //定义三级节点的文件 File testHtml = new File("test.html"); File testJS = new File("test.js"); //填充一级文件夹 root.add(imageFolder); root.add(documentFolder); root.add(systemFile); //填充二级图片文件夹 imageFolder.add(pngFolder); imageFolder.add(gifFolder); //填充二级文档文件夹 documentFolder.add(testHtml); documentFolder.add(testJS); System.out.println(root.getInfo()); //打印出来 getChildrenInfo(root.getChildren(), 1); } /** * 递归遍历文件 * @param arrayList */ @SuppressWarnings("rawtypes") private static void getChildrenInfo(ArrayList arrayList , int level){ int length = arrayList.size(); for(int m = 0;m<length;m++){ Object item = arrayList.get(m); //如果是叶子节点就直接打印出来名称 if(item instanceof File){ System.out.println(printBlank(level)+ "文件 : " + ((File) item).getInfo()); }else { //如果是分支节点就先打印分支节点的名称,再递归遍历子节点 System.out.println(printBlank(level) + "文件夹 : " + ((Folder)item).getInfo()); getChildrenInfo(((Folder)item).getChildren() , level +1); } } } private static String printBlank(int level) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < level; i++) { sb.append("*"); } return sb.toString(); } }
适配器模式
系统需要使用现有的类,而此类的接口不符合系统的需要。适配器将一个对象包装起来用以改变其接口
//已经存在的类 public class Phone { public void typecPhone() { System.out.println("信息从Typec口的手机输出。"); } } //适配接口 public interface Vga { void vgaInterface(); } // 实现一个Type-c转VGA适配器, public class Typec2Vga implements Vga{ private Phone phone; public Typec2Vga(Phone phone) { // TODO Auto-generated constructor stub this.phone = phone; } @Override public void vgaInterface() { // TODO Auto-generated method stub if(phone != null) { phone.typecPhone(); System.out.println("接收到Type-c口信息,信息转换成VGA接口中..."); System.out.println("信息已转换成VGA接口,显示屏可以对接。"); } } } public class MainClass { public static void main(String[] args) { Phone phone = new Phone(); Vga vga = new Typec2Vga(phone); vga.vgaInterface(); } }
外观模式
为子系统中的一组接口提供了一个统一的访问接口,使得子系统更加容易使用
public class CPU { public void start() { System.out.println("CPU start"); } public void shutdown() { System.out.println("CPU shutdown"); } } public class Disk { public void start() { System.out.println("Disk start"); } public void shutdown() { System.out.println("Disk shutdown"); } } public class Memory { public void start() { System.out.println("Memory start"); } public void shutdown() { System.out.println("Memory shutdown"); } } //外观 public class Computer { private CPU cpu; private Memory memory; private Disk disk; public Computer(CPU cpu, Memory memory, Disk disk) { super(); this.cpu = cpu; this.memory = memory; this.disk = disk; } public void start() { cpu.start(); memory.start(); disk.start(); } } public class MainClass { public static void main(String[] args) { CPU cpu = new CPU(); Memory memory = new Memory(); Disk disk = new Disk(); Computer computer = new Computer(cpu, memory, disk); computer.start(); } }
享元模式
通过共享技术来有效的支持大量细粒度的对象,为了尽量不创建多余的对象【线程池技术就是采用的享元模式】
public class FlyweightModel { /* * 享元模式—围棋落子 */ public static void main(String[] args) { String color = "黑"; int x = 0; int y = 0; WQFlyweight wqFlyweight; for (int i = 0; i < 5; i++) { x = (int) (19 * Math.random()); y = (int) (19 * Math.random()); if (color.equals("黑")) { color = "白"; } else { color = "黑"; } wqFlyweight = WQFlyweightFactory.getWQFlyweight(color); if (wqFlyweight != null) { wqFlyweight.put(x, y); } } } } //享元模式实现围棋落子 //1、抽象享元类(外部状态(x,y)) interface WQFlyweight { void put(int x, int y);// 外部状态,棋子位置 } //2、具体享元类(内部状态(黑,白)) class WQConFlyweight implements WQFlyweight { private String color; public WQConFlyweight(String color) { this.color = color; } @Override public void put(int x, int y) { System.out.println(color + "子:落于" + "(" + x + "," + y + ")" + "位置"); } } //3、享元工厂类 class WQFlyweightFactory { // 确保内部状态实例只有两个 private static WQFlyweight WHITE; private static WQFlyweight BLACK; private WQFlyweightFactory() { }; public static WQFlyweight getWQFlyweight(String color) { if (color.equals("白")) { if (WHITE == null) { WHITE = new WQConFlyweight("白"); } return WHITE; } else if (color.equals("黑")) { if (BLACK == null) { BLACK = new WQConFlyweight("黑"); } return BLACK; } return null; } }
代理模式
客户端并不直接调用实际对象,而是通过调用代理来间接的调用实际对象
public interface Subject { void visit(); } public class RealSubject implements Subject { private String name = "byhieg"; @Override public void visit() { System.out.println(name); } } public class DynamicProxy implements InvocationHandler { private Object object; public DynamicProxy(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = method.invoke(object, args); return result; } } public class MainClass { public static void main(String[] args) { Subject realSubject = new RealSubject(); DynamicProxy proxy = new DynamicProxy(realSubject); ClassLoader classLoader = realSubject.getClass().getClassLoader(); Subject subject = (Subject) Proxy.newProxyInstance(classLoader, new Class[]{Subject.class}, proxy); subject.visit(); } }