复合模式
综述
- 模式通常被一起使用,并被组合在同一设计解决方案中
- 复合模式在一个解决方案中结合两个或多个模式,以解决一般或重复发生的问题
类图
复合模式示例
创建多个鸭子对象
public interface IQuackable
{
void Quack();
}
public class BlueheadDuck : IQuackable
{
public void Quack()
{
Console.WriteLine("鸭子叫");
}
}
剩余3个鸭子对象省略
使用适配器模式创建一个会鹅叫的鸭子
/// <summary>
/// 鹅
/// </summary>
public class Goose
{
public void Honk() {
Console.WriteLine("鹅在叫...");
}
}
/// <summary>
/// 使用适配器模式创建一个会鹅叫的鸭子。
/// </summary>
public class GooseAdapter : IQuackable
{
Goose goose;
public GooseAdapter(Goose goose)
{
this.goose = goose;
}
public void Quack()
{
goose.Honk();
}
}
使用装饰着模式装饰为”能够叫”对象
/// <summary>
/// QuackCounter类为装饰者
/// </summary>
public class QuackCounter : IQuackable
{
IQuackable _duck;
private static int _numberOfQuacks;
public static int NumberOfQuacks
{
get
{
return _numberOfQuacks;
}
set
{
_numberOfQuacks = value;
}
}
public QuackCounter(IQuackable duck)
{
_duck = duck;
}
public void Quack()
{
_duck.Quack();
NumberOfQuacks++;
}
}
使用工厂模式代替对象的创建
/// <summary>
/// 抽象工厂类
/// </summary>
public abstract class AbstractDuckFactory
{
public abstract IQuackable CreateBlueheadDuck();
public abstract IQuackable CreatePinkheadDuck();
public abstract IQuackable CreateDuckCall();
public abstract IQuackable CreateRubberDuck();
}
/// <summary>
/// 使用工厂,创建没有被装饰的鸭子
/// </summary>
public class DuckFactory : AbstractDuckFactory
{
//使用工厂,创建没有被装饰的鸭子
public override IQuackable CreateBlueheadDuck()
{
return new BlueheadDuck();
}
//使用工厂,创建没有被装饰的鸭子
public override IQuackable CreateDuckCall()
{
return new DuckCall();
}
//使用工厂,创建没有被装饰的鸭子
public override IQuackable CreatePinkheadDuck()
{
return new PinkheadDuck();
}
//使用工厂,创建没有被装饰的鸭子
public override IQuackable CreateRubberDuck()
{
return new RubberDuck();
}
}
/// <summary>
/// 使用工厂和装饰者,创建被装饰的鸭子
/// </summary>
public class CountingDuckFactory : AbstractDuckFactory
{
//使用装饰者,创建被装饰的鸭子
public override IQuackable CreateBlueheadDuck()
{
return new QuackCounter(new BlueheadDuck());
}
//使用装饰者,创建被装饰的鸭子
public override IQuackable CreateDuckCall()
{
return new QuackCounter(new DuckCall());
}
//使用装饰者,创建被装饰的鸭子
public override IQuackable CreatePinkheadDuck()
{
return new QuackCounter(new PinkheadDuck());
}
//使用装饰者,创建被装饰的鸭子
public override IQuackable CreateRubberDuck()
{
return new QuackCounter(new RubberDuck());
}
}
使用组合和迭代器模式
/// <summary>
/// 迭代器模式
/// </summary>
public class FlockEnum : IEnumerator
{
IQuackable[] quackers;
int index = -1;
public IQuackable Current
{
get
{
try
{
return quackers[index];
}
catch (IndexOutOfRangeException)
{
throw new IndexOutOfRangeException();
}
}
}
object IEnumerator.Current
{
get
{
return Current;
}
}
public FlockEnum(IQuackable[] quackers)
{
this.quackers = quackers;
}
public bool MoveNext()
{
index++;
return (index < quackers.Count());
throw new NotImplementedException();
}
public void Reset()
{
index = -1;
}
}
/// <summary>
/// 使用组合模式和迭代器模式
/// </summary>
public class Flock : IQuackable, IEnumerable
{
IQuackable[] quackers;
public Flock(IQuackable[] quackers)
{
this.quackers = quackers;
}
public FlockEnum GetEnumerator()
{
return new FlockEnum(quackers);
}
public void Quack()
{
IEnumerator items = quackers.GetEnumerator();
while (items.MoveNext())
{
IQuackable quacker = (IQuackable)items.Current;
quacker.Quack();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
}
使用观察者模式
public class IQuackableObservable : IObservable<IQuackable>
{
private List<IObserver<IQuackable>> observers;
public IQuackableObservable()
{
observers = new List<IObserver<IQuackable>>();
}
public IDisposable Subscribe(IObserver<IQuackable> observer)
{
if (!observers.Contains(observer))
{
observers.Add(observer);
}
return new Unsubscriber(observers, observer);
}
private class Unsubscriber : IDisposable
{
private List<IObserver<IQuackable>> _observers;
private IObserver<IQuackable> _observer;
public Unsubscriber(List<IObserver<IQuackable>> observers, IObserver<IQuackable> observer)
{
this._observers = observers;
this._observer = observer;
}
public void Dispose()
{
if (_observer != null && _observers.Contains(_observer))
_observers.Remove(_observer);
}
}
public void Notify(IQuackable value)
{
IEnumerator items = observers.GetEnumerator();
while (items.MoveNext())
{
IObserver<IQuackable> item = (IObserver<IQuackable>)items.Current;
item.OnNext(value);
//item.OnNext();
}
}
}
public class IQuackableObserver : IObserver<IQuackable>
{
private IDisposable unsubscriber;
//通知提供者:某观察者将要接收通知。
public virtual void Subscribe(IObservable<IQuackable> provider)
{
if (provider != null)
{
unsubscriber = provider.Subscribe(this);
}
}
public void OnCompleted()
{
Console.WriteLine("观察员:OnCompleted");
this.Unsubscribe();
}
public void OnError(Exception error)
{
Console.WriteLine("观察员:OnError");
}
public void OnNext(IQuackable value)
{
//调用鸭子叫
value.Quack();
}
//某观察者将要取消接收通知。
public virtual void Unsubscribe()
{
unsubscriber.Dispose();
}
}
结果
DuckSimuLator duckSimuLator = new DuckSimuLator();
AbstractDuckFactory duckFactory = new CountingDuckFactory();
duckSimuLator.Simnulate(duckFactory);
internal class DuckSimuLator
{
internal void Simnulate(AbstractDuckFactory duckFactory)
{
//1.使用工厂创建鸭子
//2.使用装饰者,创建被装饰的鸭子
IQuackable blueheadDuck = duckFactory.CreateBlueheadDuck();
IQuackable pinkheadDuck = duckFactory.CreatePinkheadDuck();
IQuackable duckCall = duckFactory.CreateDuckCall();
IQuackable rubberDuck = duckFactory.CreateRubberDuck();
//使用适配器模式创建一个会鹅叫的鸭子。
IQuackable gooseDuck = new GooseAdapter(new Goose());
IQuackable[] quacks = { blueheadDuck, pinkheadDuck, duckCall, rubberDuck, gooseDuck };
//使用组合模式和迭代器模式
Flock flockOfDucks = new Flock(quacks);
Console.WriteLine("------鸭子模拟器-------");
Simnulate(flockOfDucks);
Console.WriteLine("------观察开始-------");
//使用观察者模式
IQuackableObservable provider = new IQuackableObservable();
IQuackableObserver reporter1 = new IQuackableObserver();
reporter1.Subscribe(provider);
provider.Notify(duckFactory.CreateRubberDuck());
Console.WriteLine("------观察结束-------");
Console.WriteLine("鸭子叫的次数为:" + QuackCounter.NumberOfQuacks);
}
void Simnulate(IQuackable duck)
{
duck.Quack();
}
}
输出
------鸭子模拟器-------
鸭子叫
鸭子叫
鸭鸣器在叫...
橡皮鸭在叫...
鹅在叫...
------观察开始-------
橡皮鸭在叫...
------观察结束-------
鸭子叫的次数为:5
MVC
P419-452