结构型模式:解耦不同功能
- 代理模式
- 实现方式:实现同一个接口(加上组合),或者继承
- 动态代理:在代理类比较多的情况下,可以通过动态代理,在程序运行的时候动态创建代理类
- 应用场景:监控、鉴权、统计、限流
public interface PlayGame {
void play();
}
public class LiLiPalyGame implements PlayGame{
@Override
public void play() {
System.out.println("yin yin yin");
}
}
public class PlayGameProxy implements PlayGame{
private LiLiPalyGame liLiPalyGame;
public PlayGameProxy() {
liLiPalyGame = new LiLiPalyGame();
}
@Override
public void play() {
System.out.println("pre");
liLiPalyGame.play();
System.out.println("after");
}
}
public class PlayGameDynamicProxy {
public Object createProxy(Object object){
DynamicProxy dynamicProxy = new DynamicProxy(object);
Object instance = Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), dynamicProxy);
return instance;
}
public class DynamicProxy implements InvocationHandler{
private Object proxies;
public DynamicProxy(Object obj) {
proxies = obj;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("before");
method.invoke(proxies,objects);
System.out.println("after");
return null;
}
}
}
PlayGameProxy playGameProxy = new PlayGameProxy();
playGameProxy.play();
PlayGameDynamicProxy playGameDynamicProxy = new PlayGameDynamicProxy();
PlayGame playGame = (PlayGame) playGameDynamicProxy.createProxy(new LiLiPalyGame());
playGame.play()
技术方案:
jdk
javasist
cglib
javasist&cglib通过添加依赖,性能相似
- 装饰器模式
和代理模式相似,都是组合代替继承,不同点在于,代理模式添加不相关的功能,装饰模式是扩展功能
eg:java的输入输出流,就是基于装饰器模式
带缓存的输入流
InputStream in = new FileInputStream("路径")
InputStrean bin = new BufferInputStream(in);
byte[] data = new byte[128]
while(bin.read(data) != -1){
}
- 适配器模式
偏向于"事后补救","插头装换"
public interface ITarget {
void f1();
void f2();
void f3();
}
public class Adaptee {
void fa(){}
void fb(){}
void fc(){}
}
//继承模式
public class Adaptor extends Adaptee implements ITarget {
@Override
public void f1() {
super.fa();
}
@Override
public void f2() {
super.fb();
}
@Override
public void f3() {
super.fc();
}
}
//泛型话组合模式 Android 的ListView 和ListAdapter关系
public class Adaptor2 implements ITarget{
private T adaptee;
public Adaptor2(T adaptee) {
this.adaptee = adaptee;
}
@Override
public void f1() {
adaptee.fa();
}
@Override
public void f2() {
adaptee.fb();
}
@Override
public void f3() {
adaptee.fc();
}
}
- 门面模式
目的:让调用者易调用
eg
解决性能问题,依次调三个接口合并成一个接口
解决分布式事务
- 组合模式
场景:适合树形的数据结构
实现:继承同一父类
public abstract class FileSystemNode {
private String path;
public FileSystemNode(String path) {
this.path = path;
}
public abstract int countNumOfFiles();
public abstract long countSizeOfFiles();
public String getPath() {
return path;
}
}
public class File extends FileSystemNode {
public File(String path) {
super(path);
}
@Override
public int countNumOfFiles() {
return 1;
}
@Override
public long countSizeOfFiles() {
java.io.File file = new java.io.File(getPath());
if (!file.exists()) return 0;
return file.length();
}
}
public class Directory extends FileSystemNode {
public Directory(String path) {
super(path);
}
private List subNodes = new ArrayList<>();
@Override
public int countNumOfFiles() {
int fileNum = 0;
for (int i = 0; i < subNodes.size(); i++) {
long l = subNodes.get(i).countNumOfFiles();
fileNum +=l;
}
return fileNum;
}
@Override
public long countSizeOfFiles() {
int fileSize = 0;
for (int i = 0; i < subNodes.size(); i++) {
long l = subNodes.get(i).countSizeOfFiles();
fileSize +=l;
}
return fileSize;
}
public void addSubNode(FileSystemNode fileSystemNode){
subNodes.add(fileSystemNode);
}
public void removeNode(FileSystemNode fileSystemNode){
int i = 0 ;
for (;i < subNodes.size();i++){
if (fileSystemNode.getPath().equalsIgnoreCase(subNodes.get(i).getPath())){
break;
}
}
if (i < subNodes.size()){
subNodes.remove(fileSystemNode);
}
}
}
public static void main(String[] args){
/**
* /
* /tml/
* /tml/1.txt
* /tml/book/
* /tml/book/designModel.txt
* /tml/book/Java.txt
* /wc/
* /wc/2.txt
* /wc/movie/
* /wc/movie/helloWorld.mp4
* /wc/movie/helloJava.mp4
*/
Directory fileSystemTree = new Directory("/");
Directory tmlDirectory = new Directory("/tml");
Directory wcDirectory = new Directory("/wc");
fileSystemTree.addSubNode(tmlDirectory);
fileSystemTree.addSubNode(wcDirectory);
File file1 = new File("/tml/1.txt");
Directory node_tmlDirectory = new Directory("/tml/book/");
Directory node_wcDirectory = new Directory("/wc/movie/");
File file2 = new File("/wc/2.txt");
tmlDirectory.addSubNode(file1);
tmlDirectory.addSubNode(node_tmlDirectory);
wcDirectory.addSubNode(node_wcDirectory);
wcDirectory.addSubNode(file2);
File designModelFile = new File("/tml/book/designModel.txt");
File JavaFile = new File("/tml/book/Java.txt");
File helloWorldFile = new File("/wc/movie/helloWorld.mp4");
File helloJavaFile = new File("/wc/movie/helloJava.mp4");
node_tmlDirectory.addSubNode(designModelFile);
node_tmlDirectory.addSubNode(JavaFile);
node_wcDirectory.addSubNode(helloWorldFile);
node_wcDirectory.addSubNode(helloJavaFile);
int fileNum = fileSystemTree.countNumOfFiles();
long fileSize = fileSystemTree.countSizeOfFiles();
System.out.println("fileNum: "+fileNum+" fileSize: "+fileSize);
}
- 享元模式
理解:复用,节省内存
实现:利用工厂模式,Map或List缓存创建好的对象,用的时候直接从缓存读取
实例:象棋;Word文字格式
区别:vs多例 享元是为了节省内存,缓存是为了节省时间
Integer
Integer i1 = 56;
Integer i2 = 56;
Integer i3 = new Integer(56);
Integer i4 = 128;
Integer i5 = 128;
i1 == i2 true
i2 == i3 false
i4 == i5 false
缓存-128~127
String 同理
- 桥接模式
多个变化条件,如果采用继承的话会造成类爆炸,通过对变化和实现进行隔离的一种设计模式
四个角色:(1)Abstraction抽象类,充当桥接类,聚合了行为接口(2)RefindAbstraction类,抽象类的子类,实现了抽象方法(3)Implementor,行为接口(4)ConcreteImplementorA,行为接口的实现类
/接口
public interface Brand {
void open(); //开机
void close(); //关机
void call();//打电话
}
//接口实现类
public class NOKIA implements Brand{
@Override
public void open() {
System.out.println("诺基亚手机开机");
}
@Override
public void close() {
System.out.println("诺基亚手机关机");
}
@Override
public void call() {
System.out.println("诺基亚手机打电话");
}
}
public class Newsmy implements Brand{
@Override
public void open() {
System.out.println("纽曼手机开机");
}
@Override
public void close() {
System.out.println("纽曼手机关机");
}
@Override
public void call() {
System.out.println("纽曼手机打电话");
}
}
//抽象类
public abstract class Phone {
private Brand brand;//手机品牌接口
public Phone(Brand brand) {//构造器
super();
this.brand = brand;
}
public void open() {
this.brand.open();
}
public void close() {
this.brand.close();
}
public void call() { this.brand.call(); }
}
//抽象子类
public class ButtonPhone extends Phone{
public ButtonPhone(Brand brand) {
super(brand);
}
public void open() {
super.open();
System.out.println("按键手机");
}
public void close() {
super.close();
System.out.println("按键手机");
}
public void call() {
super.call();
System.out.println("按键手机");
}
}
public class SlidePhone extends Phone{
public SlidePhone(Brand brand) {
super(brand);
}
public void open() {
super.open();
System.out.println("翻盖手机");
}
public void close() {
super.close();
System.out.println("翻盖手机");
}
public void call() {
super.call();
System.out.println("翻盖手机");
}
}
public class Client {
public static void main(String[] args) {
Phone phone1 = new ButtonPhone(new NOKIA());
phone1.open();
phone1.call();
phone1.close();
System.out.println("=======================");
Phone phone2 = new SlidePhone(new Newsmy());
phone2.open();
phone2.call();
phone2.close();
}
}