[java] كيف تختلف أنماط Proxy و Decorator و Adapter و Bridge؟



Answers

وكما تقول إجابة بيل ، فإن حالات استخدامها تختلف .

لذلك هي هياكلها.

  • كل من الوكيل و الديكور لهما نفس الواجهة لأنواعهما الملتفة ، لكن الوكيل يقوم بإنشاء مثيل تحت غطاء المحرك ، في حين يأخذ الديكور مثالاً في المنشئ.

  • يتميز كل من المهايئ والواجهات بواجهة مختلفة عن تلك التي تلتف بها. لكن المحول مشتق من واجهة موجودة ، بينما تخلق الواجهة واجهة جديدة.

  • الجسر والمحول كلاهما يشير إلى نوع موجود. لكن الجسر سوف يشير إلى نوع تجريدي ، وقد يشير المحول إلى نوع ملموس. سيسمح لك الجسر بإقران التطبيق في وقت التشغيل ، بينما لا يقوم المحول عادةً بذلك.

Question

كنت أنظر إلى نمط الوكيل ، ويبدو لي الكثير مثل أنماط الديكور والمحول والجسور. هل أسيء فهم شيء ما؟ ماهو الفرق؟ لماذا أستخدم نمط الوكيل مقابل الآخرين؟ كيف استخدمتها في الماضي في مشاريع العالم الحقيقي؟




هناك قدر كبير من التداخل في العديد من أنماط GoF. انهم جميعا بنيت على قوة تعدد الأشكال وأحيانا تختلف فقط في الحقيقة في النية. (استراتيجية مقابل الدولة)

زاد فهمي للأنماط 100 أضعاف بعد قراءة أنماط التصميم الأولى للرأس .

انا اوصي بشده به!




أعتقد أن الكود سيعطي أفكارًا واضحة (لاستكمال إجابات الآخرين أيضًا). الرجاء انظر أدناه ، (التركيز على الأنواع التي ينفذها أحد الصفوف ويلتفها)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            /* Proxy */

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("PROXY");
            Console.WriteLine(Environment.NewLine);

            //instead of creating here create using a factory method, the facory method will return the proxy
            IReal realProxy = new RealProxy();
            Console.WriteLine("calling do work with the proxy object ");
            realProxy.DoWork();

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("ADAPTER");
            Console.WriteLine(Environment.NewLine);

            /*Adapter*/
            IInHand objectIHave = new InHand();
            Api myApi = new Api();
            //myApi.SomeApi(objectIHave); /*I cant do this, use a adapter then */
            IActual myAdaptedObject = new ActualAdapterForInHand(objectIHave);
            Console.WriteLine("calling api with  my adapted obj");
            myApi.SomeApi(myAdaptedObject);


            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("DECORATOR");
            Console.WriteLine(Environment.NewLine);

            /*Decorator*/
            IReady maleReady = new Male();
            Console.WriteLine("now male is going to get ready himself");
            maleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReady = new Female();
            Console.WriteLine("now female is going to get ready her self");
            femaleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady maleReadyByBeautician = new Beautician(maleReady);
            Console.WriteLine("now male is going to get ready by beautician");
            maleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReadyByBeautician = new Beautician(femaleReady);
            Console.WriteLine("now female is going to get ready by beautician");
            femaleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            Console.ReadLine();


        }
    }

    /*Proxy*/

    public interface IReal
    {
        void DoWork();
    }

    public class Real : IReal
    {
        public void DoWork()
        {
            Console.WriteLine("real is doing work ");
        }
    }


    public class RealProxy : IReal
    {
        IReal real = new Real();

        public void DoWork()
        {
            real.DoWork();
        }
    }

    /*Adapter*/

    public interface IActual
    {
        void DoWork();
    }

    public class Api
    {
        public void SomeApi(IActual actual)
        {
            actual.DoWork();
        }
    }

    public interface IInHand
    {
        void DoWorkDifferently();
    }

    public class InHand : IInHand
    {
        public void DoWorkDifferently()
        {
            Console.WriteLine("doing work slightly different ");
        }
    }

    public class ActualAdapterForInHand : IActual
    {
        IInHand hand = null;

        public ActualAdapterForInHand()
        {
            hand = new InHand();
        }

        public ActualAdapterForInHand(IInHand hnd)
        {
            hand = hnd;
        }

        public void DoWork()
        {
            hand.DoWorkDifferently();
        }
    }

    /*Decorator*/

    public interface IReady
    {
        void GetReady();
    }

    public class Male : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
        }
    }

    public class Female : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
            Console.WriteLine("Make up....");
        }
    }

    //this is a decorator
    public class Beautician : IReady
    {
        IReady ready = null;

        public Beautician(IReady rdy)
        {
            ready = rdy;
        }

        public void GetReady()
        {
            ready.GetReady();
            Console.WriteLine("Style hair ");

            if (ready is Female)
            {
                for (int i = 1; i <= 10; i++)
                {
                    Console.WriteLine("doing ready process " + i);
                }

            }
        }
    }

}



بالتفصيل تنفيذ التنفيذ ، أجد فرقا بين الوكيل وديكور ، محول ، واجهة ... في التنفيذ المشترك لهذه الأنماط هناك كائن الهدف ملفوفة بواسطة كائن الإحاطة. يستخدم العميل ترفق الكائن بدلاً من الكائن الهدف. ويلعب الكائن المستهدف فعليًا جزءًا مهمًا داخل بعض أساليب إحاطة الكائن.

ومع ذلك ، في حالة البروكسي ، يمكن أن يؤدي تشغيل الكائن إلى تشغيل بعض الأساليب في حد ذاته ، فإنه يقوم فقط بتهيئة كائن الهدف عندما يقوم العميل باستدعاء بعض الطرق التي يحتاج إليها الكائن الهدف للمشاركة فيه. هذه هي عملية التهيئة البطيئة. في حالة وجود أنماط أخرى ، فإن الكائن الذي يتم إرفاقه يعتمد فعليًا على الكائن المستهدف. يتم دائمًا تهيئة الكائن المستهدف جنبًا إلى جنب مع تضمين الكائن في الصانعين / المستويين.

شيء آخر ، وكيل يفعل بالضبط ما يفعله الهدف في حين أن أنماط أخرى تضيف المزيد من الوظائف لاستهدافها.




إنها متشابهة تمامًا ، والخطوط بينهما رمادية تمامًا. أقترح عليك قراءة إدخالات نمط الوكيل و Decorator في c2 wiki.

الإدخالات والمناقشات هناك واسعة للغاية ، وترتبط أيضًا بمقالات أخرى ذات صلة. بالمناسبة ، فإن c2 wiki ممتاز عندما تتساءل عن الفروق الدقيقة بين الأنماط المختلفة.

لتلخيص إدخالات c2 ، أود أن أقول أن الديكور يضيف / يغير من السلوك ، لكن الوكيل له علاقة أكبر بالسيطرة على الوصول (مثل التثبيت الفوري ، الوصول عن بعد ، الأمن ، الخ). ولكن كما قلت ، فإن الخطوط بينهما رمادية ، وأرى إشارات إلى وكلاء يمكن النظر إليهم بسهولة على أنهم مصممون والعكس صحيح.




هذا الاقتباس من Head First Design Patterns

التعاريف تنتمي إلى الكتاب. الأمثلة تنتمي لي.

Decorator - لا يغير الواجهة ، ولكنه يضيف المسؤولية. افترض أن لديك واجهة سيارة ، عند تنفيذ ذلك لنموذج مختلف من السيارة (s ، sv ، sl) قد تحتاج إلى إضافة المزيد من المسؤولية لبعض الموديلات. مثل قد فتحة السقف ، الوسادة الهوائية الخ ..

محول - تحويل واجهة واحدة إلى أخرى. لديك واجهة سيارة وتريد أن تتصرف مثل سيارة جيب. حتى تأخذ السيارة وتعديلها وتحويلها إلى سيارة جيب. لأنها ليست سيارة جيب حقيقية. لكن أفعال مثل سيارة جيب.

الواجهة - تجعل الواجهة أكثر بساطة. افترض أن لديك سيارة ، طائرة ، واجهات سفينة. في الواقع ، كل ما تحتاجه هو فصل يُرسل الأشخاص من موقع إلى آخر. تريد واجهة لتحديد ما لاستخدام المركبة. ثم تقوم بجمع كل هذه الإشارات المرجعية تحت مظلة واحدة واتركها تقرر / تفوضها لتبقيها بسيطة.

Head First: "إن الواجهة لا تبسط فقط واجهة ، بل تفصل العميل عن نظام فرعي من المكونات. قد تقوم الواجهات والمحوّلات بلف الطبقات المتعددة ، لكن هدف الواجهة هو التبسيط ، في حين أن المحول هو تحويل الواجهة إلى شيء مختلف. "






Links