我正在查看代理模式,对我来说,它看起来非常像装饰器、适配器和桥接模式。我是不是误解了什么?有什么不同?为什么我要使用代理模式而不是其他模式?在过去的实际项目中,您是如何使用它们的?
当前回答
代理、装饰器、适配器和桥接器都是“包装”类的变体。但它们的用途不同。
Proxy could be used when you want to lazy-instantiate an object, or hide the fact that you're calling a remote service, or control access to the object. Decorator is also called "Smart Proxy." This is used when you want to add functionality to an object, but not by extending that object's type. This allows you to do so at runtime. Adapter is used when you have an abstract interface, and you want to map that interface to another object which has similar functional role, but a different interface. Bridge is very similar to Adapter, but we call it Bridge when you define both the abstract interface and the underlying implementation. I.e. you're not adapting to some legacy or third-party code, you're the designer of all the code but you need to be able to swap out different implementations. Facade is a higher-level (read: simpler) interface to a subsystem of one or more classes. Suppose you have a complex concept that requires multiple objects to represent. Making changes to that set of objects is confusing, because you don't always know which object has the method you need to call. That's the time to write a Facade that provides high-level methods for all the complex operations you can do to the collection of objects. Example: a Domain Model for a school section, with methods like countStudents(), reportAttendance(), assignSubstituteTeacher(), and so on.
其他回答
它们非常相似,而且它们之间的线条是灰色的。我建议您阅读c2 wiki中的代理模式和装饰器模式条目。
那里的条目和讨论相当广泛,也链接到其他相关文章。顺便说一下,c2 wiki在了解不同模式之间的细微差别时非常有用。
总结c2项,我认为装饰器添加/更改行为,但代理与访问控制(延迟实例化,远程访问,安全等)有更多关系。但正如我所说,它们之间的界线是灰色的,我看到对代理的引用很容易被视为装饰器,反之亦然。
所有这四种模式都涉及到用外部对象/类包装内部对象/类,因此它们在结构上非常相似。我将通过目的来概述不同之处:
代理将访问从外部封装到内部。 装饰器用外部修改或扩展内部的行为。 适配器转换接口从内部到外部。 桥将行为的不变部分(外部)与变量或平台依赖部分(内部)分开。
通过内外物体之间的界面变化:
在代理接口中是相同的。 在Decorator接口中是相同的。 在适配器接口形式上不同,但实现相同的目的。 桥接接口在概念上是不同的。
在许多GoF模式中有大量的重叠。它们都建立在多态性的力量之上,有时只是意图不同。(战略vs.国家)
在阅读了头部优先设计模式之后,我对模式的理解增加了100倍。
我强烈推荐!
这是引用自 头部优先的设计模式
定义属于书。例子属于我。
装饰器——不改变界面,但增加了责任。假设你有一个汽车界面, 当您为不同型号的汽车(s, sv, sl)实现此功能时,您可能需要为某些型号添加更多的职责。比如有天窗,安全气囊等。
适配器—将一个接口转换为另一个接口。你有一个汽车界面,你想让它像吉普车一样工作。所以你把车开过来,改装成吉普车。因为这不是真正的吉普车。但它就像一辆吉普车。
Facade -使界面更简单。假设你有汽车、飞机、轮船接口。实际上,你所需要的只是一个将人从一个位置发送到另一个位置的类。你想让门面决定用什么车。然后将所有这些接口引用收集到一个保护伞下,并让它决定/委托以保持简单。
首先:“facade不仅简化了接口,还将客户端与子系统解耦 的组件。 外观和适配器可以包装多个类,但是外观的目的是简化 适配器的作用是将接口转换为不同的东西。”
我相信代码会给出一个清晰的想法(补充其他答案)。请参见下面,(关注类实现和包装的类型)
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);
}
}
}
}
}
推荐文章
- 如何向一个5岁的孩子解释依赖注入?
- 我怎么知道什么时候创建一个接口?
- 在PHP5中创建单例设计模式
- 什么时候我们应该使用观察者和可观察对象?
- 在类主体中调用类静态方法?
- 在哪里放置AutoMapper.CreateMaps?
- 使用Enum实现单例(Java)
- 由Jon Skeet撰写的《Singleton》澄清
- 为什么c#不提供c++风格的'friend'关键字?
- 如何在python抽象类中创建抽象属性?
- 如何实现typescript装饰器?
- 是否有一个装饰器来缓存函数返回值?
- Redux @connect装饰器中的“@”(at符号)是什么?
- 什么是包装器类?
- MVC, MVP和MVVM设计模式在编码c#方面有什么不同