面接でよく見られるデザイン

13581 ワード

今日はいくつかの一般的なデザインモデルを共有します.これらのデザインモデルは私が顔で見たものです.つまり、会社が面接の過程でよく試験を受ける可能性が高いことを意味しますが、絶対ではありません.23パターンより全部覚えるのは手間がかかるようです.だからここでは、私が考えているいくつかのよくあるデザインモデルについて、関連資料の整理を行い、復習と記憶を便利にします.
単一モード
コンセプト
JAvaにおける単例モードはよく見られる設計モードであり、単例モードの書き方はいくつかあり、ここでは主に2種類を紹介する:怠け者式単例、餓漢式単例.シングル・インスタンス・モードには、1、シングル・インスタンス・クラスに1つのインスタンスしかないという特徴があります.2、単一のインスタンスクラスは、独自の一意のインスタンスを作成する必要があります.3、単一のクラスは、他のすべてのオブジェクトにこのインスタンスを提供する必要があります.
コードインスタンス
//   
public class Singleton {

    //     volatile                    
    private static volatile Singleton singleton = null;

    private Singleton() {
        System.out.println("init class");
    }

    //      :   synchronize          
    public synchronized static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }

        return singleton;
    }

    //      :                                         
    public static Singleton getInstance1() {
        if (singleton == null) {

            synchronized (singleton) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }

        return singleton;
    }

    //      :                             
    private static class LazyLoader {
        private static final Singleton SINGLETON = new Singleton();
    }

    public static final Singleton getInstance3() {
        return LazyLoader.SINGLETON;
    }
}

単一のモードを実現するための3つの方法を示した.
1.第1の方法でsynchronizeキーワードを直接使用することで、スレッドのセキュリティが保証されます.ただし、呼び出すたびに同期してパフォーマンスに影響を与える必要があります.また、単一のインスタンスモードでは、返されるインスタンスを使用する確率よりも作成される確率がはるかに低い
  • 第2の方法は、インスタンスを返す方法の内部でsynchronizeコードブロックを使用してスレッドセキュリティを実現することを二重検出することであり、インスタンスがnullの場合にインスタンスの作成と同期のプロセスが行われることを確保し、毎回同期が必要となる消費を回避する
  • である.
    2つ目の方法には問題があります
    A,Bの2つのスレッドを例にとると,a>A,Bスレッドが同時に1番目のif判定b>Aに入ってまずsynchronizedブロックに入り,instanceがnullであるためsingleton=new Singleton()を実行する.c>JVM内部の最適化メカニズムのため、JVMはSingletonインスタンスに割り当てられた空きメモリをいくつか描きました.instanceメンバーに値を割り当てます(この時点でJVMはこのインスタンスの初期化を開始していないことに注意)、Aはsynchronizedブロックを離れた.d>Bはsynchronizedブロックに入り、instanceはnullではないため、synchronizedブロックをすぐに離れ、そのメソッドを呼び出すプログラムに結果を返す.e>このときBスレッドはSingletonインスタンスを使用しようとしたが、初期化されていないことに気づき、エラーが発生した.
    簡単に言えば、あなたのnewのオブジェクトは初期化が完了していないので、突然不思議な感じがします.newが初期化されたのではないでしょうか.ここでは、JAVAの比較的下位レベルのものについて、オブジェクトの作成の概要を3つのステップにまとめることができます:1.オブジェクトのメモリ領域2を割り当てます.オブジェクト3を初期化します.オブジェクトをそのメモリアドレスに向けるステップ2と3で命令の並べ替えが発生する可能性があり、必ずしも3を先に実行してから2を実行する可能性があるため、上記の状況が発生したとは限らない.このときvolatileキーワードや第3の方法で実現することを考えることができます
  • 第3の方法は静的内部クラスを使用することであり、一例のモードは内部クラスを使用して一例の実現を維持することであり、JVM内部のメカニズムは一つのクラスがロードされたとき、このクラスのロードプロセスがスレッド反発であることを保証することができる.これにより、getInstanceを初めて呼び出すと、JVMはinstanceが一度だけ作成されることを保証し、instanceに割り当てられたメモリの初期化が完了することを保証します.これにより、上記の問題を心配する必要はありません.同時に、この方法は、1回目の呼び出し時にのみ反発メカニズムを使用するため、低パフォーマンスの問題
  • を解決する.
    シーンの操作
    コンピュータシステムでは、スレッドプール、キャッシュ、ログオブジェクト、ダイアログボックス、プリンタ、グラフィックスカードのドライバオブジェクトが単一の例として設計されることが多い.
    ファクトリメソッドモードと抽象ファクトリモード
    コンセプト
    ファクトリ・モード(Factory Pattern)はJavaで最も一般的な設計モードの1つです.このタイプの設計モードは、オブジェクトの作成に最適な方法を提供する作成モードに属します.ファクトリ・モードでは、オブジェクトの作成時にクライアントに対して作成ロジックを暴露することはなく、共通のインタフェースを使用して新しく作成されたオブジェクトを指します.
    細かく分けて3種類ありますが、1つは簡単な工場で、1つは工場方法で抽象的な工場です.GOFは『設計モード』で工場モードを2種類に分けた.工場方法モード(Factory Method)と抽象工場モード(Abstract Factory)である.単純工場モード(Simple Factory)を工場方法モードの特例と見なし、両者を1種類に分類した.
    コードインスタンス
    package com.Model.Factory;
    
    //    
    public interface Sender {
    
        public void send();
    }
    
    
    package com.Model.Factory;
    
    //    
    public class Factory {
    
        //               
        public Sender produceSender(String senderType) {
            if (senderType == null) {
                return null;
            } else if (senderType.equals("sms")) {
                return new SMSSender();
            } else if (senderType.equals("email")) {
                return new EmailSender();
            } else {
                System.out.println("invaild senderType....");
                return null;
            }
        }
    }
    
    //    EMail             
    class EmailSender implements Sender {
    
        @Override
        public void send() {
            System.out.println("sending a email...");
        }
    }
    
    //    SMS             
    class SMSSender implements Sender {
    
        @Override
        public void send() {
            System.out.println("sending a sms....");
    
        }
    
    }
    

    次はファクトリメソッドモードのコードインスタンスです.ファクトリの部分だけがいくつかの違いがあります.
    //                                           
    class SenderFactory {
        public static Sender produceEmail() {
            return new EmailSender();
        }
    
        public static Sender produceSMS() {
            return new SMSSender();
        }
    }
    

    ファクトリメソッドと単純ファクトリの違いは、staticを使用し、文字列を使用して作成タイプを判断する必要がなく、nullインスタンスの作成を回避し、ファクトリオブジェクトを生成する必要がなく、特定の製品インスタンスの生成を直接呼び出すメリットです.
    以下は抽象ファクトリモード
    抽象ファクトリの生成
    package com.Model.Factory;
    
    //                
    public interface Producer {
    
        public Sender provide();
    }
    
    

    具体的な工場
    //     email   
    class EmailFactory implements Producer {
    
        @Override
        public Sender provide() {
            return new EmailSender();
        }
    
    }
    
    //     SMS   
    class SMSFactory implements Producer {
    
        @Override
        public Sender provide() {
            return new SMSSender();
        }
    }
    
    

    抽象工場の利点は,元の工場のコードを修正せずに直接拡張できることである.例えば、もう一つの電子送信機を拡張したい場合は、抽象工場のインタフェースを継承し、製品のインタフェースを継承するだけです.そしてそれぞれ実現すればよい.
    シーンの操作
    オブジェクトインスタンスを構築するのに便利です.オブジェクトインスタンスを構築する詳細や複雑なプロセスに関心を持つ必要はありません.また、構築されたインスタンスプロセスは複雑です.
    プロキシモード
    コンセプト
    他のオブジェクトへのアクセスを制御するプロキシを提供します.オブジェクトに直接アクセスするときに発生する問題です.たとえば、アクセスするオブジェクトはリモートマシンにあります.オブジェクト向けシステムでは、オブジェクトの作成にコストがかかる場合や、セキュリティ制御が必要な場合や、プロセス外のアクセスが必要な場合など、特定の理由でオブジェクトに直接アクセスすると、ユーザーやシステム構造に多くのトラブルが発生します.このオブジェクトにアクセスするときに、このオブジェクトに対するアクセス層を追加できます.
    コードインスタンス
    package com.Model.Proxy;
    
    //    
    public interface BuyCar {
        public void buycar();
    }
    
    package com.Model.Proxy;
    
    public class People implements BuyCar {
    
        private int cash;
        private String vip;
        private String username;
    
        @Override
        public void buycar() {
            System.out.println(username + " is vip so he/she can buy any car...");
        }
    
        public int getCash() {
            return cash;
        }
    
        public void setCash(int cash) {
            this.cash = cash;
        }
    
        public String getVip() {
            return vip;
        }
    
        public void setVip(String vip) {
            this.vip = vip;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
    }
    
    //                  
    class ProxyBuyCar implements BuyCar {
    
        private People People;
    
        public People getPeople() {
            return People;
        }
    
        public void setPeople(People people) {
            People = people;
        }
    
        @Override
        public void buycar() {
            if (People.getVip().equals("vip")) {
                People.buycar();
            } else if (People.getCash() >= 50000) {
                System.out.println(People.getUsername() + "buy a new car trade over...");
            } else {
                System.out.println(People.getUsername() + "people can't buy a car ");
            }
        }
    
    }
    

    重要なのはエージェントクラスであり、いくつかのルールを利用して動作の発生を制限することです.
    シーンの操作
    1、Windows内のショートカット.2、猪八戒は高翠兰を探しに行った结果、孙悟空が変わった.高翠兰の外见を抽象化し、高翠兰本人と孙悟空がこのインターフェースを実现した.猪八戒は高翠兰を访问した时、これが孙悟空だとは见えなかった.だから、孙悟空は高翠兰の代理类だと言った.3、汽車の切符を買うのは駅で買うとは限らないし、代理店に行ってもいいです.4、小切手または銀行預金証書は口座の資金の代理である.小切手は市場取引で現金の代わりに使用され、発行者の口座の資金のコントロールを提供します.5、spring aop.
    エージェントモデルとして最も古典的なのはSpring AOPであり,ターゲットクラスとメソッドをスライス強化する機能であり,ターゲットクラスに基づいてスライスロジックを追加することで,プログラムビジネスに関係のないコンテンツをいくつか完成させる.主に2つの実装モードがあります.1つはJDKの動的エージェントであり、1つはCglibエージェントです.
    この2つの違いは、JDK動的エージェントがインタフェースを実現したターゲットクラスCglibのみをエージェントすることができ、Cglibを必要としないことである.クラスベースのエージェント原理は、ターゲットクラスにサブクラスを生成し、それをカバーし、実現するすべての方法であり、すべてのCglibがfinal修飾クラスを代行できないことを強化することである.
    ここではJDKエージェントの例を示します.
    package com.Model.Proxy;
    
    //    
    public interface SubjectOperations {
        //     
        public void print();
    
        //          
        public void printfStr(String string);
    }
    
    package com.Model.Proxy;
    
    public class RealSubject implements SubjectOperations {
    
        @Override
        public void print() {
            System.out.println("               ");
    
        }
    
        @Override
        public void printfStr(String string) {
            // TODO Auto-generated method stub
            System.out.println("       :  " + string);
        }
    
    }
    
    
    package com.Model.Proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class LogHandler implements InvocationHandler {
    
        private Object ImpClass;
    
        public LogHandler(Object realObject) {
            this.ImpClass = realObject;
        }
    
        public Object bind(Object impclass) {
            this.ImpClass = impclass;
    
            return Proxy.newProxyInstance(impclass.getClass().getClassLoader(), impclass.getClass().getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            System.out.println("                             .....         ");
    
            System.out.println("Method:   " + method);
    
            method.invoke(ImpClass, args);
    
            System.out.println("             ,                     ");
    
            return null;
        }
    
        public static void main(String[] args) {
    
        }
    }
    
    class Client {
        public static void main(String[] args) {
            RealSubject subject = new RealSubject();
            LogHandler handler = new LogHandler(subject);
    
            //                  
            SubjectOperations pSubject1 = (SubjectOperations) handler.bind(subject);
            System.out.println(pSubject1.getClass().getName());
    
            pSubject1.print();
            pSubject1.printfStr("YYYYY");
        }
    }
    
    
         :
    
    com.sun.proxy.$Proxy0
                                 .....         
    Method:   public abstract void com.Model.Proxy.SubjectOperations.print()
                   
                 ,                     
                                 .....         
    Method:   public abstract void com.Model.Proxy.SubjectOperations.printfStr(java.lang.String)
           :  YYYYY
                 ,                     
    

    ロールチェーンモード
    コンセプト
    複数のオブジェクトがリクエストを処理する機会を与え、リクエストの送信者と受信者との結合関係を回避し、このオブジェクトをチェーンに接続し、このチェーンに沿ってリクエストを1つのオブジェクトが処理するまで伝達します.
    コードインスタンス
    まず、この業務の具体的な情報に名前や費用などが含まれている清算クラスを作成します.
    package com.Model.Chain_of_Responsibility;
    
    public class MoneyRequest {
    
        private String name;
        private double money;
    
        public MoneyRequest(String name, double money) {
            super();
            this.name = name;
            this.money = money;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public double getMoney() {
            return money;
        }
    
        public void setMoney(double money) {
            this.money = money;
        }
    
    }
    
    

    次は抽象クラスの抽象的な承認オブジェクトで、清算要求を処理します.
    package com.Model.Chain_of_Responsibility;
    
    public abstract class Leader {
    
        protected String name;
        protected Leader successor;
    
        public Leader(String name) {
            this.name = name;
        }
    
        public void Setsuccessor(Leader successor) {
            this.successor = successor;
        }
    
        public abstract void handleRequest(MoneyRequest moneyRequest);
    
    }
    

    次は、承認を実現するための条件とルールの具体的な実装クラスです.
    package com.Model.Chain_of_Responsibility;
    
    public class Director extends Leader {
    
        public Director(String name) {
            super(name);
            // TODO Auto-generated constructor stub
        }
    
        public void handleRequest(MoneyRequest moneyRequest) {
            if (moneyRequest.getMoney() < 300) {
                System.out.println("     " + name + "       " + moneyRequest.getName() + "        ,          "
                        + moneyRequest.getMoney());
            } else {
                this.successor.handleRequest(moneyRequest);
            }
        }
    
    }
    
    
    package com.Model.Chain_of_Responsibility;
    
    public class GeneralManager extends Leader {
        public GeneralManager(String name) {
            super(name);
            // TODO Auto-generated constructor stub
        }
    
        public void handleRequest(MoneyRequest moneyRequest) {
            if (moneyRequest.getMoney() < 2000) {
                System.out.println("       " + name + "             " + moneyRequest.getName() + "         ,          "
                        + moneyRequest.getMoney());
            } else {
                System.out
                        .println(moneyRequest.getName() + "                  " + moneyRequest.getMoney() + "        ,  !");
            }
        }
    }
    
    
    package com.Model.Chain_of_Responsibility;
    
    public class Manager extends Leader {
    
        public Manager(String name) {
            super(name);
            // TODO Auto-generated constructor stub
        }
    
        public void handleRequest(MoneyRequest moneyRequest) {
            if (moneyRequest.getMoney() < 800) {
                System.out.println("     " + name + "       " + moneyRequest.getName() + "        ,          "
                        + moneyRequest.getMoney());
            } else {
                this.successor.handleRequest(moneyRequest);
            }
        }
    }
    
    

    シーンの操作
    JAVA WEBにおけるApache Tomcat対Encodingの処理,Struts 2のブロッキング,jsp servletのFilter.
    参考出所:23種類の設計モードまとめ設計モードjava設計モード全面詳細解_Java開発における23種類の設計モデル