把会变化的部分独立取出并封装起来,不要和其他不需要变化的代码混在一起。
针对接口编程,而不是针对实现编程。
多用组合,少用继承。
类应该对扩展开放,对修改封闭。
策略模式
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的用户。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Demo { public interface FlyBehavior { void fly(); } public class FlyWithWings:FlyBehavior { public void fly() { Console.WriteLine("I'am flying!!"); } } public class FlyNoWay:FlyBehavior { public void fly() { Console.WriteLine("I can't fly"); } } public class FlyRocketPowered : FlyBehavior { public void fly() { Console.WriteLine("I'am flying with a rocket!"); } } }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Demo { public interface QuackBehavior { void quack(); } public class Quack:QuackBehavior { public void quack() { Console.WriteLine("Quack"); } } public class MuteQuack:QuackBehavior { public void quack() { Console.WriteLine("<<Silence>>"); } } public class Squeak:QuackBehavior { public void quack() { Console.WriteLine("Squeak"); } } }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Demo { public abstract class Duck { protected FlyBehavior _flyBehavior; protected QuackBehavior _quackBehaviour; public Duck() { } public abstract void Display(); public void PerformFly() { _flyBehavior.fly(); //委托给行为类的对象进行处理 } public void PerformQuack() { _quackBehaviour.quack(); //委托给行为类的对象进行处理 } public void Swim() { Console.WriteLine("All ducks float!!"); } public void SetFlyBehavior(FlyBehavior fb) { _flyBehavior = fb; } public void SetQuackBehavior(QuackBehavior qb) { _quackBehaviour = qb; } } // public class MallarDuck:Duck { public MallarDuck() { _flyBehavior = new FlyWithWings(); _quackBehaviour = new Quack(); } public override void Display() { Console.WriteLine("I'am a real Mallard duck!"); } } public class ModelDuck : Duck { public ModelDuck() { _flyBehavior = new FlyNoWay(); _quackBehaviour = new Quack(); } public override void Display() { Console.WriteLine("I'am a model duck!"); } } }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Threading; using System.Threading.Tasks; namespace Demo { class Program { static void Main(string[] args) { Duck mallard = new MallarDuck(); mallard.PerformFly(); mallard.PerformQuack(); mallard.Display(); Duck model = new ModelDuck(); model.PerformFly(); model.SetFlyBehavior(new FlyRocketPowered()); model.PerformFly(); Console.ReadKey(); } } }
观察者模式
观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到消息并自动更新。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Demo { public interface Subject { void registerObserver(Observer o); void removeObserver(Observer o); void notifyObservers(); } public interface Observer { void update(float temp, float himidity, float pressure); } public interface DisplayElement { void display(); } }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Demo { public class WeatherData:Subject { private List<Observer> observers; private float temperature; private float humidity; private float pressure; public WeatherData() { observers = new List<Observer>(); } public void registerObserver(Observer o) { observers.Add(o); } public void removeObserver(Observer o) { if (observers.Contains(o)) observers.Remove(o); } public void notifyObservers() { for(int i=0;i<observers.Count();++i) { observers[i].update(temperature,humidity,pressure); } } public void measurementsChanged() { notifyObservers(); } public void SetMeasurements(float t,float h,float p) { this.temperature = t; this.humidity = h; this.pressure = p; measurementsChanged(); } } }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Demo { public class CurrentConditionsDisplay:Observer,DisplayElement { private float tempterature; private float humidity; private Subject weatherData; public CurrentConditionsDisplay(Subject w) { this.weatherData = w; weatherData.registerObserver(this); } public void update(float t, float h, float p) { this.tempterature = t; this.humidity = h; display(); } public void display() { string msg = string.Format("Current conditions: {0}F degrees and {1} humidity", tempterature, humidity); Console.WriteLine(msg); } } }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Threading; using System.Threading.Tasks; namespace Demo { class Program { static void Main(string[] args) { WeatherData _weatherData = new WeatherData(); CurrentConditionsDisplay _conditionDisplay = new CurrentConditionsDisplay(_weatherData); _weatherData.SetMeasurements(80, 65, 30.5f); _weatherData.SetMeasurements(50, 62, 33.5f); Console.ReadKey(); } } }
使用C#提供的IObservable<>和IObserver<>接口。
The IObserver<T> and IObservable<T> interfaces provide a generalized mechanism for push-based notification, also known as the observer design pattern. The IObservable<T> interface represents the class that sends notifications (the provider); the IObserver<T>interface represents the class that receives them (the observer).T represents the class that provides the notification information. In some push-based notifications, the IObserver<T> implementation and T can represent the same type.
The provider must implement a single method, Subscribe, that indicates that an observer wants to receive push-based notifications.Callers to the method pass an instance of the observer. The method returns an IDisposable implementation that enables observers to cancel notifications at any time before the provider has stopped sending them.
At any given time, a given provider may have zero, one, or multiple observers. The provider is responsible for storing references to observers and ensuring that they are valid before it sends notifications. The IObservable<T> interface does not make any assumptions about the number of observers or the order in which notifications are sent.
The provider sends the following three kinds of notifications to the observer by calling IObserver<T> methods:
-
The current data. The provider can call the IObserver<T>.OnNext method to pass the observer a T object that has current data, changed data, or fresh data.
-
An error condition. The provider can call the IObserver<T>.OnError method to notify the observer that some error condition has occurred.
-
No further data. The provider can call the IObserver<T>.OnCompleted method to notify the observer that it has finished sending notifications.
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Demo { public struct Location { double lat, lon; public Location(double latitude, double longitude) { this.lat = latitude; this.lon = longitude; } public double Latitude { get { return this.lat; } } public double Longitude { get { return this.lon; } } } /// public class LocationTracker : IObservable<Location> { public LocationTracker() { observers = new List<IObserver<Location>>(); } private List<IObserver<Location>> observers; public IDisposable Subscribe(IObserver<Location> observer) { if (!observers.Contains(observer)) observers.Add(observer); return new Unsubscriber(observers, observer); } private class Unsubscriber : IDisposable { private List<IObserver<Location>> _observers; private IObserver<Location> _observer; public Unsubscriber(List<IObserver<Location>> observers, IObserver<Location> observer) { this._observers = observers; this._observer = observer; } public void Dispose() { if (_observer != null && _observers.Contains(_observer)) _observers.Remove(_observer); } } public void TrackLocation(Nullable<Location> loc) { foreach (var observer in observers) { if (!loc.HasValue) observer.OnError(new LocationUnknownException()); else observer.OnNext(loc.Value);//向观察者提供新数据 } } public void EndTransmission() { foreach (var observer in observers.ToArray()) if (observers.Contains(observer)) observer.OnCompleted(); observers.Clear(); } } public class LocationUnknownException : Exception { internal LocationUnknownException() { } } // public class LocationReporter : IObserver<Location> { private IDisposable unsubscriber; private string instName; public LocationReporter(string name) { this.instName = name; } public string Name { get { return this.instName; } } public virtual void Subscribe(IObservable<Location> provider) { if (provider != null) unsubscriber = provider.Subscribe(this); } public virtual void OnCompleted() { Console.WriteLine("The Location Tracker has completed transmitting data to {0}.", this.Name); this.Unsubscribe(); } public virtual void OnError(Exception e) { Console.WriteLine("{0}: The location cannot be determined.", this.Name); } public virtual void OnNext(Location value) { Console.WriteLine("{2}: The current location is {0}, {1}", value.Latitude, value.Longitude, this.Name); } public virtual void Unsubscribe() { unsubscriber.Dispose(); } } }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Threading; using System.Threading.Tasks; namespace Demo { class Program { static void Main(string[] args) { // Define a provider and two observers. LocationTracker provider = new LocationTracker(); LocationReporter reporter1 = new LocationReporter("FixedGPS"); reporter1.Subscribe(provider); LocationReporter reporter2 = new LocationReporter("MobileGPS"); reporter2.Subscribe(provider); provider.TrackLocation(new Location(47.6456, -122.1312)); reporter1.Unsubscribe(); provider.TrackLocation(new Location(47.6677, -122.1199)); provider.TrackLocation(null); provider.EndTransmission(); Console.ReadKey(); } } }
装饰者模式
装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。