结构性模式(三):代理模式、享元模式
2020-03-25 本文已影响0人
JBryan
1、代理模式
在不改变原始类(或叫被代理类)的情况下,通过引入代理类来给原始类附加功能。一般情况下,我们让代理类和原始类实现同样的接口。但是,如果原始类并没有定义接口,并且原始类代码并不是我们开发维护的。在这种情况下,我们可以通过让代理类继承原始类的方法来实现代理模式。
1.1、实例说明
在某个应用软件中,需要记录业务方法的调用日志,在不修改现有业务类的基础上为每一个类提供一个日志记录代理类,如在业务方法method()调用之前输出“方法method()”被调用,调用之后如果没有异常,则输出“方法method()调用成功”,否则输出“method()调用失败”。在代理类中调用真实业务类的业务方法,使用代理模式设计该日志记录模块的结构,绘制类图并编程模拟实现。
1.2、实例类图
代理模式.jpg1.3、实例代码
package com.ljessie.designpattern.structural.proxy;
public interface AbstractLog {
void method();
}
public class BusinessClass implements AbstractLog {
@Override
public void method() {
System.out.println("真实业务方法!");
}
}
public class LoggerProxy implements AbstractLog {
private BusinessClass businessClass;
public LoggerProxy(){
businessClass = new BusinessClass();
}
@Override
public void method() {
System.out.println("方法method()被调用!");
try{
businessClass.method();
System.out.println("方法method()调用成功!");
}catch (Exception e){
System.out.println("方法method()调用异常!");
}
}
}
public class Client {
public static void main(String[] args) {
AbstractLog al = new LoggerProxy();
al.method();
}
}
代理模式在Spring AOP中的应用可参考:https://www.jianshu.com/p/58eb4b0a8a85
2、享元模式
所谓“享元”,顾名思义就是被共享的单元。享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。具体来讲,当一个系统中存在大量重复对象的时候,我们就可以利用享元模式,将对象设计成享元,在内存中只保留一份实例,供多处代码引用,这样可以减少内存中对象的数量,以起到节省内存的目的。
实际上,不仅仅相同对象可以设计成享元,对于相似对象,我们也可以将这些对象中相同的部分(字段),提取出来设计成享元,让这些大量相似对象引用这些享元。
2.1、实例说明
使用享元模式设计一个围棋软件,在系统中只存在一个白棋对象和一个黑棋对象,但是它们可以在棋盘的不同位置显示多次。
2.2、实例类图
享元模式.jpg2.3、实例代码
public class Coordinates {
private int x;
private int y;
public Coordinates(int x,int y){
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
/**
* 围棋棋子类,抽象享元类
*/
public abstract class IgoChessman {
abstract String getColor();
public void locate(Coordinates coordinates){
System.out.println("棋子颜色:"+this.getColor()+",棋子位置:"+coordinates.getX()+","+coordinates.getY());
}
}
/**
* 具体享元类
*/
public class BlackIgoChessman extends IgoChessman {
@Override
String getColor() {
return "黑色";
}
}
/**
* 具体享元类
*/
public class WhiteIgoChessman extends IgoChessman {
@Override
String getColor() {
return "白色";
}
}
public class IgoChessmanFactory {
private static IgoChessmanFactory instance =
new IgoChessmanFactory();
private static Hashtable ht;
private IgoChessmanFactory(){
ht = new Hashtable();
IgoChessman black = new BlackIgoChessman();
IgoChessman white = new WhiteIgoChessman();
ht.put("b",black);
ht.put("w",white);
}
public static IgoChessmanFactory getInstance(){
return instance;
}
public IgoChessman getIgoChessman(String color){
return (IgoChessman) ht.get(color);
}
}
public class Client {
public static void main(String[] args) {
IgoChessman black1,black2,white1,white2;
IgoChessmanFactory factory = IgoChessmanFactory.getInstance();
black1 = factory.getIgoChessman("b");
black2 = factory.getIgoChessman("b");
white1 = factory.getIgoChessman("w");
white2 = factory.getIgoChessman("w");
System.out.println("两颗黑棋是否相同:"+(black1==black2));
System.out.println("两颗白棋是否相同:"+(white1==white2));
black1.locate(new Coordinates(1,2));
white1.locate(new Coordinates(2,4));
}
}
运行结果:
两颗黑棋是否相同:true
两颗白棋是否相同:true
棋子颜色:黑色,棋子位置:1,2
棋子颜色:白色,棋子位置:2,4