1、 创建一个接口并实现
public interface Image { void display(); } public class RealImage implements Image { private String fileName; public RealImage(String fileName){ this.fileName = fileName; loadFromDisk(fileName); } @Override public void display() { System.out.println("Displaying " + fileName); } private void loadFromDisk(String fileName){ System.out.println("Loading " + fileName); } } public class ProxyImage implements Image{ private RealImage realImage; private String fileName; public ProxyImage(String fileName){ this.fileName = fileName; } @Override public void display() { if(realImage == null){ realImage = new RealImage(fileName); } realImage.display(); } }
2、当被请求时,使用 ProxyImage 来获取 RealImage 类的对象
public class ProxyPatternDemo { public static void main(String[] args) { Image image = new ProxyImage("test_10mb.jpg"); //图像将从磁盘加载 image.display(); System.out.println(""); //图像将无法从磁盘加载 image.display(); } }
动态代理
动静态代理的区别,什么场景使用? 静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。 静态代理事先知道要代理什么,而动态代理不知道要代理什么。只有在运行时才知道。 动态代理是实现JDK的InvocationHandler接口的invoke方法,但注意代理的是接口。也就是你的业务类必须实现的接口,通过proxy里的newProxyInstance得到代理对象。 还有一种动态代理CGLIB,代理的是类,不需要业务类继承接口,通过派生的子类来实现接口,通过在运行时,动态修改字节码达到修改类的目的。 AOP编程是基于动态代理实现的,比如spring框架。
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。
适配器模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能
举例:
适配器模式:
意图:
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
主要解决:
主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的
何时使用:
1、为媒体播放器和更高级的媒体播放器创建接口
public interface MediaPlayer { public void play(String audioType, String fileName); } public interface AdvancedMediaPlayer { public void playVlc(String fileName); public void playMp4(String fileName); }
2、创建实现了 AdvancedMediaPlayer 接口的实体类
public class VlcPlayer implements AdvancedMediaPlayer{ @Override public void playVlc(String fileName) { System.out.println("Playing vlc file. Name: "+ fileName); } @Override public void playMp4(String fileName) { //什么也不做 } } public class Mp4Player implements AdvancedMediaPlayer{ @Override public void playVlc(String fileName) { //什么也不做 } @Override public void playMp4(String fileName) { System.out.println("Playing mp4 file. Name: "+ fileName); } }
3、创建实现了 MediaPlayer 接口的适配器类
public class MediaAdapter implements MediaPlayer { AdvancedMediaPlayer advancedMusicPlayer; public MediaAdapter(String audioType){ if(audioType.equalsIgnoreCase("vlc") ){ advancedMusicPlayer = new VlcPlayer(); } else if (audioType.equalsIgnoreCase("mp4")){ advancedMusicPlayer = new Mp4Player(); } } @Override public void play(String audioType, String fileName) { if(audioType.equalsIgnoreCase("vlc")){ advancedMusicPlayer.playVlc(fileName); }else if(audioType.equalsIgnoreCase("mp4")){ advancedMusicPlayer.playMp4(fileName); } } }
4、创建实现了 MediaPlayer 接口的实体类
public class AudioPlayer implements MediaPlayer { MediaAdapter mediaAdapter; @Override public void play(String audioType, String fileName) { //播放 mp3 音乐文件的内置支持 if(audioType.equalsIgnoreCase("mp3")){ System.out.println("Playing mp3 file. Name: "+ fileName); } //mediaAdapter 提供了播放其他文件格式的支持 else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){ mediaAdapter = new MediaAdapter(audioType); mediaAdapter.play(audioType, fileName); } else{ System.out.println("Invalid media. "+ audioType + " format not supported"); } } }
5、使用 AudioPlayer 来播放不同类型的音频格式
public class AdapterPatternDemo { public static void main(String[] args) { AudioPlayer audioPlayer = new AudioPlayer(); audioPlayer.play("mp3", "beyond the horizon.mp3"); audioPlayer.play("mp4", "alone.mp4"); audioPlayer.play("vlc", "far far away.vlc"); audioPlayer.play("avi", "mind me.avi"); } }
适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性文艺。 主要分为三类: 类的适配器模式、对象的适配器模式、接口的适配器模式。 适配器模式,即定义一个包装类,用于包装不兼容接口的对象
类的适配器模式:
public static class Source { public void method1() { System.out.println("this is original method!"); } } public interface Targetable { // 与原类中方法相同 public void method1(); // 新类的方法 public void method2(); } public static class Adapter extends Source implements Targetable { @Override public void method2() { System.out.println("this is Targetable method!"); } } public static void main(String[] args) { Targetable targetable = new Adapter(); targetable.method1(); targetable.method2(); }
对象的适配器模式:
public static class Source { public void method1() { System.out.println("this is original method!"); } } public interface Targetable { // 与原类中方法相同 public void method1(); // 新类的方法 public void method2(); } public static class Wrapper implements Targetable { private Source source; public Wrapper(Source source) { super(); this.source = source; } @Override public void method1() { source.method1(); } @Override public void method2() { System.out.println("this is Targetable method!"); } } public static void main(String[] args) { Source source = new Source(); Targetable targetable = new Wrapper(source); targetable.method1(); targetable.method2(); }
接口的适配器模式:
接口的适配器模式是这样的: 有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显就比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,而我们不和原接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。
装饰器模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能
举例:
装饰模式:
意图:
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活
主要解决:
一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀
1、创建一个接口并实现
public interface Shape { void draw(); } public class Rectangle implements Shape { @Override public void draw() { System.out.println("Shape: Rectangle"); } } public class Circle implements Shape { @Override public void draw() { System.out.println("Shape: Circle"); } }
2、创建实现了 Shape 接口的抽象装饰类
public abstract class ShapeDecorator implements Shape { protected Shape decoratedShape; public ShapeDecorator(Shape decoratedShape){ this.decoratedShape = decoratedShape; } public void draw(){ decoratedShape.draw(); } }
3、创建扩展了 ShapeDecorator 类的实体装饰类
public class RedShapeDecorator extends ShapeDecorator { public RedShapeDecorator(Shape decoratedShape) { super(decoratedShape); } @Override public void draw() { decoratedShape.draw(); setRedBorder(decoratedShape); } private void setRedBorder(Shape decoratedShape){ System.out.println("Border Color: Red"); } }
4、使用 RedShapeDecorator 来装饰 Shape 对象
public class DecoratorPatternDemo { public static void main(String[] args) { Shape circle = new Circle(); Shape redCircle = new RedShapeDecorator(new Circle()); Shape redRectangle = new RedShapeDecorator(new Rectangle()); System.out.println("Circle with normal border"); circle.draw(); System.out.println("\nCircle of red border"); redCircle.draw(); System.out.println("\nRectangle of red border"); redRectangle.draw(); } }
装饰器模式Decorator,就是给一个对象增加一些新的功能,而且是动态的, 要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。
public interface Sourceable { public void method(); } public static class Source implements Sourceable { @Override public void method() { System.out.println("the original method!"); } } public static class Decorator implements Sourceable { private Sourceable source; public Decorator(Sourceable source) { super(); this.source = source; } @Override public void method() { System.out.println("before decorator!"); source.method(); System.out.println("after decorator!"); } } public static void main(String[] args) { Sourceable source = new Source(); Sourceable obj = new Decorator(source); obj.method(); }
1、创建一个接口并实现
public interface Shape { void draw(); } public class Rectangle implements Shape { @Override public void draw() { System.out.println("Rectangle::draw()"); } } public class Square implements Shape { @Override public void draw() { System.out.println("Square::draw()"); } } public class Circle implements Shape { @Override public void draw() { System.out.println("Circle::draw()"); } }
2、创建一个外观类
public class ShapeMaker { private Shape circle; private Shape rectangle; private Shape square; public ShapeMaker() { circle = new Circle(); rectangle = new Rectangle(); square = new Square(); } public void drawCircle(){ circle.draw(); } public void drawRectangle(){ rectangle.draw(); } public void drawSquare(){ square.draw(); } }
3、使用该外观类画出各种类型的形状
public class FacadePatternDemo { public static void main(String[] args) { ShapeMaker shapeMaker = new ShapeMaker(); shapeMaker.drawCircle(); shapeMaker.drawRectangle(); shapeMaker.drawSquare(); } }
桥接模式(Bridge Pattern)是用于把抽象化与实现化解耦,使得二者可以独立变化
桥接模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类,这两种类型的类可被结构化改变而互不影响
也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以独立的变化。
举例:
意图:
将抽象部分与实现部分分离,使它们都可以独立的变化
主要解决:
在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活
何时使用:
实现系统可能有多个角度分类,每一种角度都可能变化
如何解决:
把这种多角度分类分离出来,让它们独立变化,减少它们之间耦合
猪八戒从天蓬元帅转世投胎到猪,转世投胎的机制将尘世划分为两个等级,即:灵魂和肉体,前者相当于抽象化,后者相当于实现化
生灵通过功能的委派,调用肉体对象的功能,使得生灵可以动态地选择
墙上的开关,可以看到的开关是抽象的,不用管里面具体怎么实现的
1、 创建桥接实现接口和实现类
public interface DrawAPI { public void drawCircle(int radius, int x, int y); } public class RedCircle implements DrawAPI { @Override public void drawCircle(int radius, int x, int y) { System.out.println("Drawing Circle[ color: red, radius: " + radius +", x: " +x+", "+ y +"]"); } } public class GreenCircle implements DrawAPI { @Override public void drawCircle(int radius, int x, int y) { System.out.println("Drawing Circle[ color: green, radius: " + radius +", x: " +x+", "+ y +"]"); } }
2、使用 DrawAPI 接口创建抽象类 Shape
public abstract class Shape { protected DrawAPI drawAPI; protected Shape(DrawAPI drawAPI){ this.drawAPI = drawAPI; } public abstract void draw(); } public class Circle extends Shape { private int x, y, radius; public Circle(int x, int y, int radius, DrawAPI drawAPI) { super(drawAPI); this.x = x; this.y = y; this.radius = radius; } public void draw() { drawAPI.drawCircle(radius,x,y); } }
3、使用 Shape 和 DrawAPI 类画出不同颜色的圆
public class BridgePatternDemo { public static void main(String[] args) { Shape redCircle = new Circle(100,100, 10, new RedCircle()); Shape greenCircle = new Circle(100,100, 10, new GreenCircle()); redCircle.draw(); greenCircle.draw(); } }
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象
组合模式创建了一个包含自己对象组的类,该类提供了修改相同对象组的方式。
举例:
合成模式:
何时使用:
如何解决:
树枝和叶子实现统一接口,树枝内部组合该接口
关键代码:
树枝内部组合该接口,并且含有内部属性 List,里面放 Component
1、创建 Employee 类,该类带有 Employee 对象的列表
public class Employee { private String name; private String dept; private int salary; private List<Employee> subordinates; //构造函数 public Employee(String name,String dept, int sal) { this.name = name; this.dept = dept; this.salary = sal; subordinates = new ArrayList<Employee>(); } public void add(Employee e) { subordinates.add(e); } public void remove(Employee e) { subordinates.remove(e); } public List<Employee> getSubordinates(){ return subordinates; } public String toString(){ return ("Employee :[ Name : "+ name +", dept : "+ dept + ", salary :" + salary+" ]"); } }
2、 使用 Employee 类来创建和打印员工的层次结构
public class CompositePatternDemo { public static void main(String[] args) { Employee CEO = new Employee("John","CEO", 30000); Employee headSales = new Employee("Robert","Head Sales", 20000); Employee headMarketing = new Employee("Michel","Head Marketing", 20000); Employee clerk1 = new Employee("Laura","Marketing", 10000); Employee clerk2 = new Employee("Bob","Marketing", 10000); Employee salesExecutive1 = new Employee("Richard","Sales", 10000); Employee salesExecutive2 = new Employee("Rob","Sales", 10000); CEO.add(headSales); CEO.add(headMarketing); headSales.add(salesExecutive1); headSales.add(salesExecutive2); headMarketing.add(clerk1); headMarketing.add(clerk2); //打印该组织的所有员工 System.out.println(CEO); for (Employee headEmployee : CEO.getSubordinates()) { System.out.println(headEmployee); for (Employee employee : headEmployee.getSubordinates()) { System.out.println(employee); } } } }
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能
享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象
举例:
享元模式:FLYWEIGHT在拳击比赛中指最轻量级。
意图:
运用共享技术有效地支持大量细粒度的对象
主要解决:
在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建
何时使用:
定义一个 Shape 接口和实现了 Shape 接口的实体类 Circle
定义工厂类 ShapeFactory
ShapeFactory 有一个 Circle 的 HashMap ,其中键名为 Circle 对象的颜色
无论何时接收到请求,都会创建一个特定颜色的圆
ShapeFactory 检查它的 HashMap 中的 circle 对象,如果找到 Circle 对象,则返回该对象,否则将创建一个存储在 hashmap 中以备后续使用的新对象,并把该对象返回到客户端
定义类 FlyWeightPatternDemo 使用 ShapeFactory 来获取 Shape 对象
它将向 ShapeFactory 传递信息( red / green / blue/ black / white ),以便获取它所需对象的颜色
1、定义一个接口和实现类
public interface Shape { void draw(); } public class Circle implements Shape { private String color; private int x; private int y; private int radius; public Circle(String color){ this.color = color; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void setRadius(int radius) { this.radius = radius; } @Override public void draw() { System.out.println("Circle: Draw() [Color : " + color +", x : " + x +", y :" + y +", radius :" + radius); } }
2、创建一个工厂,生成基于给定信息的实体类的对象
public class ShapeFactory { private static final HashMap<String, Shape> circleMap = new HashMap(); public static Shape getCircle(String color) { Circle circle = (Circle)circleMap.get(color); if(circle == null) { circle = new Circle(color); circleMap.put(color, circle); System.out.println("Creating circle of color : " + color); } return circle; } }
3、使用该工厂,通过传递颜色信息来获取实体类的对象
public class FlyweightPatternDemo { private static final String colors[] = { "Red", "Green", "Blue", "White", "Black" }; public static void main(String[] args) { for(int i=0; i < 20; ++i) { Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor()); circle.setX(getRandomX()); circle.setY(getRandomY()); circle.setRadius(100); circle.draw(); } } private static String getRandomColor() { return colors[(int)(Math.random()*colors.length)]; } private static int getRandomX() { return (int)(Math.random()*100 ); } private static int getRandomY() { return (int)(Math.random()*100); } }