美文网首页Java设计模式
《设计模式之美》(三:结构型模式)

《设计模式之美》(三:结构型模式)

作者: 文艺的程序狗 | 来源:发表于2020-08-10 10:42 被阅读0次

    结构型模式:解耦不同功能

    1. 代理模式
      • 实现方式:实现同一个接口(加上组合),或者继承
      • 动态代理:在代理类比较多的情况下,可以通过动态代理,在程序运行的时候动态创建代理类
      • 应用场景:监控、鉴权、统计、限流
    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通过添加依赖,性能相似
    
    1. 装饰器模式
      和代理模式相似,都是组合代替继承,不同点在于,代理模式添加不相关的功能,装饰模式是扩展功能
    eg:java的输入输出流,就是基于装饰器模式
    带缓存的输入流
    InputStream in = new FileInputStream("路径")
    InputStrean bin = new BufferInputStream(in);
    byte[] data = new byte[128]
    while(bin.read(data) != -1){
    }
    
    
    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<T extends Adaptee> 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();
        }
    }
    
    1. 门面模式
      目的:让调用者易调用
    eg
    解决性能问题,依次调三个接口合并成一个接口
    解决分布式事务
    
    1. 组合模式
      场景:适合树形的数据结构
      实现:继承同一父类
    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<FileSystemNode> 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);
        }
    
    1. 享元模式
      理解:复用,节省内存
      实现:利用工厂模式,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. 桥接模式

    相关文章

      网友评论

        本文标题:《设计模式之美》(三:结构型模式)

        本文链接:https://www.haomeiwen.com/subject/xjofdktx.html