代码设计模式:一句话直击内涵与意义、极简代码示例、基础3类27种,以及更多概念与视角

有些设计模式日用而不知,有些设计模式看似概念复杂实则内核简单,还有些设计模式化繁为简直至少即是多——本文,将在极简形式下,传递出基础设计模式最核心的基本思想,一共3类27种,即:创建型模式6种、结构型模式9种、行为型模式12种。

以下示例,是基于C#与Java语法的“伪代码”,并进行了“大量简化”“改变默认”(可能还有别的一些语法),主旨在于表意清晰,从而可以快速地理解回顾——每个设计模式,都给出了直击内涵意义的一句话概括。

最后,还有更多的概念视角

主题目录如下:

  • 创建型模式6种
  • 结构型模式9种
  • 行为型模式12种
  • 设计模式的意义
  • 更多的设计模式
  • 结语

创建型模式6种(Creational Patterns)

这些设计模式处理对象的创建——其特点在于,外部无法直接实例化对象。

1,单例模式(Singleton Pattern)

  • 内涵:只有一个对象实例,可以全局访问。
  • 意义:全局获取,唯一实例的功能与数据。
class Singleton
{// 私有限制外部修改private static Singleton instance = new();// 私有限制new实例化private Singleton();// 获取全局唯一实例Singleton Get() => instance;
}void Client()
{// 客户端,获取的s1等于s2s1 = Singleton.Get();s2 = Singleton.Get();
}

2,简单工厂模式(Simple Factory Pattern)

  • 内涵:工厂根据不同参数,创建不同实现的接口对象。
  • 意义:隐藏对象配置,集中对象管理,简化对象获取。
// 不同的操作实现不同的计算
interface IOperation : int Do(num1, num2);// 实现加法操作
class Add implements IOperation : int Do(num1, num2) => num1 + num2;
// 实现减法操作
class Sub implements IOperation : int Do(num1, num2) => num1 - num2;// 操作工厂根据操作类型,创建操作对象
// 增加新的类型,需要修改此处已有代码
class OperationFactory : static IOperation Create(type) => switch(type)
{case '+': return new Add();case '-': return new Sub();default : throw("不支持的操作类型"); 
}void Client()
{// 客户端计算加法OperationFactory.Create('+').Do(1, 2);// 客户端计算减法OperationFactory.Create('-').Do(5, 3);
}

3,工厂方法模式(Factory Method Pattern)

  • 内涵:接口工厂创建接口对象,具体实现自由增加。
  • 意义:隐藏工厂与对象的配置,可以扩展无需修改。
// 不同记录器,实现不同的日志
interface ILogger : void Log();class FileLogger    implements ILogger : void Log() => Print("这是文件日志");
class ConsoleLogger implements ILogger : void Log() => Print("这是控制台日志");// 不同的记录器工厂,创建不同的记录器
interface ILoggerFactory : ILogger Create();class FileLoggerFactory    implements ILoggerFactory : ILogger Create() => new FileLogger();
class ConsoleLoggerFactory implements ILoggerFactory : ILogger Create() => new ConsoleLogger();// 扩展工厂与对象的实现,不影响客户端
ILogger CreateBy(ILoggerFactory loggerFactory) => loggerFactory.Create();void Client()
{// 客户端创建,文件日志CreateBy(new FileLoggerFactory())   .Log();// 客户端创建,控制台日志CreateBy(new ConsoleLoggerFactory()).Log();
}

4,抽象工厂模式(Abstract Factory Pattern)

  • 内涵:接口工厂创建一组接口对象,具体实现自由增加。
  • 意义:隐藏对象集合的创建复杂性,简化对象集合调用。
// 不同系统的按钮,实现不同的绘制
interface IButton : void Draw();class WinButton implements IButton : void Draw() => Print("Win Button");
class MacButton implements IButton : void Draw() => Print("Mac Button");// 不同系统的文本,实现不同的绘制
interface IText : void Draw();class WinText implements IText : void Draw() => Print("Win Text");
class MacText implements IText : void Draw() => Print("Mac Text");// 不同系统的图形界面,实现不同的绘制
interface IUIFactory : IButton CreateButton(), IText CreateText();class WinFactory implements IUIFactory 
{IButton CreateButton() => new WinButton();IText   CreateText  () => new WinText  ();
}class MacFactory implements IUIFactory 
{IButton CreateButton() => new MacButton();IText   CreateText  () => new MacText  ();
}void Client()
{// 客户端根据系统,选择对应工厂IUIFactory uiFactory;if (isWin()) {uiFactory = new WinFactory();} else if (isMac()) {uiFactory = new MacFactory();       }else {throw("不支持的系统");}// 客户端使用工厂,创建相关对象集合,实现相关功能集合uiFactory.CreateButton().Draw();uiFactory.CreateText  ().Draw();
}

5,建造者模式(Builder Pattern)

  • 内涵:复杂对象分解成多个部分,每个部分独立构建。
  • 意义:降低复杂对象创建难度,可自由替换某个部分。
class Computer 
{string cpu;string gpu;string ram;string hdd;// 只能通过Builder,来实例化ComputerComputer(Builder builder);
}class Builder
{private Computer computer;// 创建内部Computer实例Builder() => this.computer = new Computer(this);Builder BuildCPU(cpu) => this.computer.cpu = cpu;Builder BuildGPU(gpu) => this.computer.gpu = gpu;Builder BuildRAM(ram) => this.computer.ram = ram;Builder BuildHDD(hdd) => this.computer.hdd = hdd;Computer GetComputer() => this.computer;
}void Client()
{// 客户端可以自由替换Computer的某个部分,也可以放到不同的地方去构建computer = new Builder().BuildCPU("cpu").BuildGPU("gpu").BuildRAM("ram").BuildHDD("hdd").GetComputer();
}

6,原型模式(Prototype Pattern)

  • 内涵:通过复制而不是构造,来创建对象。
  • 意义:提高对象创建性能,节省过程资源。
// 不同对象,实现不同的克隆
interface IPrototype : object Clone();class ComplexObject implements IPrototype : object Clone() => this.DeepCopy();void Client()
{// 创建复杂对象,需要进行大量计算,以及外部资源调用,如网络、数据库、认证、审核等等co = new ComplexObject();// 客户端直接复制,没有复杂计算与资源调用c1 = co.Clone();c2 = co.Clone();
}

结构型模式9种(Structural Patterns)

这些设计模式处理对象的组合——其特点在于,将旧对象转换成新对象。

1,适配器模式(Adapter Pattern)、包装器模式(Wrapper Pattern)

  • 内涵:将一个对象转换成,所需要的对象。
  • 意义:使得不同系统,可以相互适配兼容。
// 目标接口
interface INewTarget : void NewRequest();class OldTarget : void OldRequest() => Print("旧对象的旧请求");// 适配器让旧对象,可以实现新对象的接口
class Adapter implements INewTarget
{OldTarget oldTarget;// 获取需要适配的旧对象Adapter(oldTarget) => this.oldTarget = oldTarget;// 用旧对象实现,新对象的接口void NewRequest() => this.oldTarget.OldRequest();
}// 只接受新对象的方法
void OnlyNeedNewTarget(INewTarget newTarget) => newTarget.NewRequest();void Client()
{oldTarget = new OldTarget();// 客户端通过适配器,将旧对象当成新对象使用OnlyNeedNewTarget(new Adapter(oldTarget));
}

2,装饰器模式(Decorator Pattern)

  • 内涵:基于对象实例,添加对象接口的功能。
  • 意义:通过传递对象,来组合功能逐步增强。
// 不同的咖啡,不同的制作
interface ICoffee : void Make();class Coffee implements ICoffee : void Make() => Print("一杯咖啡");// 不改变咖啡接口,给咖啡加牛奶
class MilkDecorator implements ICoffee
{private ICoffee coffee;MilkDecorator(ICoffee coffee) => this.coffee = coffee;void Make(){this.coffee.Make();Print("加入牛奶");}
}// 不改变咖啡接口,给咖啡加冰块
class IceDecorator implements ICoffee
{private ICoffee coffee;IceDecorator(ICoffee coffee) => this.coffee = coffee;void Make(){this.coffee.Make();Print("加入冰块");}
}void Client()
{coffee = new Coffee();// 客户端制作一杯咖啡coffee.Make();milkCoffee = new MilkDecorator(coffee);// 客户端制作一杯咖啡 + 牛奶milkCoffee.Make();iceCoffee = new IceDecorator(coffee);// 客户端制作一杯咖啡 + 冰块iceCoffee.Make();// 客户端制作一杯咖啡 + 牛奶 + 冰块new IceDecorator(milkCoffee).Make();
}

注意,与继承相比,装饰器避免了,暴露父类的复杂细节,以及获得父类的无用结构。

3,代理模式(Proxy Pattern)

  • 内涵:代替原对象处理访问,并施加额外控制。
  • 意义:代理不改变功能,只是控制功能的使用。
class Image
{// 实例化图片的时候去加载Image()        => Print("加载图片");void Display() => Print("显示图片");
}class ImageProxy
{private Image image;void Display(){// 只有image为null,才会newimage ??= new Image();image.Display();}
}void Client()
{// 客户端实例化图片代理,此时没有加载图片image = new ImageProxy();// 第一次显示时,才会延迟加载图片image.Display(); // 第二次显示,不再加载图片image.Display(); 
}

注意,与装饰器相比,代理不会增强功能,只是控制功能的使用,如权限、时机、统计、日志、路由等等。

4,外观模式(Facade Pattern)、门面模式

  • 内涵:封装复杂功能,提供简化的使用方式。
  • 意义:隐藏系统的复杂性,简单化功能调用。
class AudioLoader  : void LoadAudio  () => Print(“载入音频”);
class AudioDecoder : void DecodeAudio() => Print(“解码音频”);
class AudioPlayer  : void PlayAudio  () => Print(“播放音频”); class AudioFacade
{private AudioLoader  loader;private AudioDecoder decoder;private AudioPlayer  player;AudioFacade(loader, decoder, player) => (this.loader, this.decoder, this.player) = (loader, decoder, player);// 外观对象提供简化播放调用void Play() {this.loader .LoadAudio  ();this.decoder.DecodeAudio();this.player .PlayAudio  ();}
}void Client()
{loader  = new AudioLoader ();decoder = new AudioDecoder();player  = new AudioPlayer ();facade  = new AudioFacade(loader, decoder, player);// 客户端使用外观对象,简化音频播放,隐藏播放细节facade.Play();
}

5,桥接模式(Bridge Pattern)

  • 内涵:通过接口,来组合不同的功能。
  • 意义:接口自由组合,实现自由替换。
// 不同颜色,实现不同上色 
interface IColor : void ApplyColor();class Red   implements IColor : void ApplyColor() => Print("表面喷红色");
class Green implements IColor : void ApplyColor() => Print("表面喷绿色");abstract class Shape
{protected IColor color;Shape(color) => this.color = color;abstract void Draw();
}class Circle inherits Shape
{override void Draw(){Print("绘制圆形");this.color.ApplyColor();}
}class Rect inherits Shape
{override void Draw(){Print("绘制矩形");this.color.ApplyColor();}
}void Client()
{// 客户端,绘制红色圆形new Circle(new Red  ()).Draw();// 客户端,绘制绿色矩形new Rect  (new Green()).Draw();
}

注意:

  • 与抽象工厂相比,桥接是使用接口实现的功能,抽象工厂是创建实现接口的对象。
  • 与装饰器相比,桥接是平行组合接口实现功能,装饰器是嵌套组合接口增强功能。

6,组合模式(Composite Pattern)

  • 内涵:将对象组成树形结构,每个节点含有一个节点集合。
  • 意义:统一整体与部分的操作接口,可递归处理每个节点。
// 不同节点,绘制自己
interface INode : void Paint();class Leaf implements INode : void Paint() => Print("这是树叶");
class Root implements INode
{private List<INode> nodes = new();void Add(node) => this.nodes.Add(node);void Paint(){Print("这是树根,以及子节点");foreach (node in this.nodes) node.Paint();}
}void Client()
{root1 = new Root();root1.Add(new Leaf());root2 = new Root();root2.Add(new Leaf());// 客户端,root可以添加leaf和root(自己),实际中可以用root充当leaf会更统一root2.Add(root1);// 客户端,leaf(部分)和root(整体)有相同的操作,某个root也可以看成某个部分root2.Paint();
}

7,对象池模式(Object Pool Pattern)

  • 内涵:缓存对象,重用对象的空间与功能。
  • 意义:减少内存的使用与操作,提高性能。
// 可池化对象
class Poolable
{// 出池子前,要初始化Poolable Init () => Print("初始化");// 进池子前,要重置(释放资源或防止误用)Poolable Reset() => Print("重置");
}class Pool
{// 缓存使用过的对象private Stack cache = new();// 对象池不空,就返回缓存的对象,否则创建一个public Poolable Get() => cache.Count > 0 ? pool.Pop().Init() : new Poolable().Init();// 对象用完放回池子,缓存起来public void Return(poolable) => cache.Push(poolable.Reset());
}void Client()
{pool      = new Pool();poolable1 = pool.Get();poolable2 = pool.Get();pool.Return(poolable1);// 客户端,从对象池获取缓存的对象poolable3 = pool.Get();
}

8,享元模式(Flyweight Pattern)

  • 内涵:共享对象,共用对象的数据与状态。
  • 意义:减少内存的浪费与膨胀,提高性能。
class Character
{private char c;Character(c) => this.c = c;void Draw()  => Print("自动排版绘制字符");
}class CharacterFactory
{private static Dictionary<c, Character> cache = new();static Character Get(c){if (cache.ContainsKey(c) == false){cache[c] = new Character(c);}return cache[c];}
}void Client()
{txt = "aabbccabc";foreach (c in txt){// 客户端,共享重复的元对象,即abcCharacterFactory.Get(c).Draw();}
}

注意,与对象池相比,享元是对象共用,即一个对象用在多处(内存共用),对象池是对象重用,即一个对象销毁再建(内存重用)。

9,过滤器模式(Filter Pattern)、标准模式(Criteria Pattern)

  • 内涵:按照某些规则,过滤符合条件的对象集合。
  • 意义:不需要了解实现细节,组合使用过滤规则。
// 不同的标准,过滤不同的人
interface ICriteria : List<Person> Filter(persons);class Person 
{ string name;int    age;
}class NameCriteria implements ICriteria
{private string name;NameCriteria(name) => this.name = name;List<Person> Filter(persons) => persons.Where(p => p.Name == name);
}class AgeCriteria implements ICriteria
{private int age;AgeCriteria(age) => this.age = age;List<Person> Filter(persons) => persons.Where(p => p.Age == age);
}class AndCriteria implements ICriteria
{private ICriteria criteria1;private ICriteria criteria2;AndCriteria(criteria1, criteria2) => (this.criteria1, this.criteria2) = (criteria1, criteria2);List<Person> Filter(persons) => criteria2.Filter(criteria1.Filter(persons));
}void Client()
{nameCriteria = new NameCriteria("瑞克");    ageCriteria  = new AgeCriteria (66);// 客户端,过滤出名叫瑞克且66岁的人persons = new AndCriteria(nameCriteria, ageCriteria).Filter(personList);
}

行为型模式12种(Behavioral atterns

这些设计模式处理对象的交互——其特点在于,将改变都封装到独立的对象。

1,策略模式(Strategy Pattern)

  • 内涵:封装复杂算法,实现对象行为接口。
  • 意义:自由扩展对象行为,无需修改对象。
// 不同的策略,不同的行为
interface IStrategy : void Execute();class KillPlan     implements IStrategy : void Execute() => Print("伐谋");
class KillAlliance implements IStrategy : void Execute() => Print("伐交");
class KillArmy     implements IStrategy : void Execute() => Print("伐兵");class Machine
{private IStrategy strategy;Machine(strategy)  => this.strategy = strategy;void Set(strategy) => this.strategy = strategy;void Execute()     => this.strategy.Execute();
}void Client()
{Machine = new Machine(new KillPlan());// 客户端,执行"伐谋"machine.Execute();  machine.Set(new KillAlliance());// 客户端,执行"伐交"machine.Execute(); machine.Set(new KillArmy());// 客户端,执行"伐兵"machine.Execute();  
}

注意:

  • 与抽象工厂相比,策略是切换对象行为,抽象工厂是创建不同功能的对象。
  • 与桥接相比,策略是对象行为单独变化,桥接是对象与功能两者独立变化。

2,模板方法模式(Template Method Pattern)

  • 内涵:固定算法的结构与流程,由具体对象实现细节。
  • 意义:共享通用的流程与步骤,自定义实现特殊步骤。
abstract class TeaMaker
{// 模板方法,定义泡茶流程void MakeTea(){BoilWater();BrewTea  ();PourInto ();Print("茶已做好");}// 抽象方法,留给子类实现abstract void BoilWater();abstract void BrewTea  ();abstract void PourInto ();
}// 制作绿茶
class GreenTea inherits TeaMaker
{override void BoilWater() => Print("烧85度纯净水");override void BrewTea  () => Print("泡3分钟");override void PourInto () => Print("倒入玻璃杯");
}// 制作红茶
class BlackTea inherits TeaMaker
{override void BoilWater() => Print("烧100度纯净水");override void BrewTea  () => Print("泡5分钟");override void PourInto () => Print("倒入陶瓷杯");
}void Client()
{// 客户端,制作绿茶new GreenTea().MakeTea();// 客户端,制作红茶new BlackTea().MakeTea();
}

3,观察者模式(Observer Pattern)、发布订阅模式(Publish Subscribe Pattern)

  • 内涵:对象状态改变,通知注册的观察者处理。
  • 意义:一对多关系,实现自动化低耦合的协作。
// 观察者,可以收到更新通知
interface IObserver : void Update(message);class Watch implements IObserver : void Update(message) => Print("更新信息:{message}");
class Phone implements IObserver : void Update(message) => Print("更新信息:{message}");// 可被观察者,可以发送通知给观察者
interface IObservable : void Add(observer), void Notify(message);class CarSystem implements IObservable
{private List<IObserver> observerList = new();// 添加观察者void Add(observer)   => this.observerList.Add(oberver);// 通知观察者void Notify(message) => foreach (observer in this.observerList) observer.Update(message);
}void Client()
{CarSystem = new CarSystem();CarSystem.Add(new Watch());CarSystem.Add(new Phone());// 客户端,被观察者(主题)通知观察者(订阅),状态的改变CarSystem.Notify("有人正在试图打开车门");
}

4,状态模式(State Pattern)

  • 内涵:封装对象行为到状态对象,切换状态对象改变对象行为。
  • 意义:解耦对象与状态行为,简化对象状态行为的切换与扩展。
interface IState : void Handle(animal);class Fight  implements IState : void Handle(animal) => Print("战斗状态");
class Flight implements IState : void Handle(animal) => Print("逃跑状态");
class Freeze implements IState : void Handle(animal) => Print("僵住状态"); 
class Idle   implements IState : void Handle(animal) => Print("空闲状态"); class Animal
{private IState state;Animal(state) => this.SetState(state);void SetState(state){this.state = state;this.state.Handle(this);}
}void Client()
{// 客户端,空闲状态的动物,遇到不同情况,切换不同状态animal = new Animal(new Idle());if (Has("情敌")){animal.SetState(new Fight());} else if (Has("天敌")){animal.SetState(new Flight()); }else if (Has("群敌")){animal.SetState(new Freeze()); }
}

5,命令模式(Command Pattern)

  • 内涵:将请求封装成命令对象,发送给调用者处理。
  • 意义:实现命令的排序、队列、并行、延迟、撤销。
// 不同的命令,不同的执行
interface ICommand : void Execute();// 开灯命令
class LightOn implements ICommand
{LightOn(light) => this.light = light;void Execute() => this.light.TurnOn();
}// 关灯命令
class LightOff implements ICommand
{LightOff(light) => this.light = light;void Execute()  => this.light.TurnOff();
}// 命令的执行者
class Light
{void TurnOn () => Print("开灯");void TurnOff() => Print("关灯");
}// 命令调用者
class UI
{private ICommand command;void SetCommand(command) => this.command = command;void Click()             => command?.Execute();
}void Client()
{// 命令执行者light    = new Light   ();// 请求绑定执行者,形成命令lightOn  = new LightOn (light);lightOff = new LightOff(light);// 命令调用者ui       = new UI();ui.SetCommand(lightOn);// 客户端,调用开灯命令ui.Click();  ui.SetCommand(lightOff);// 客户端,调用关灯命令ui.Click(); 
}

注意,与策略相比,命令封装的是请求与执行,策略封装的是行为算法,前者需求明确直接选择,后者需要匹配问题灵活选择。

6,责任链模式(Chain of Responsibility Pattern)

  • 内涵:对象处理不了请求,就转发给另一个对象。
  • 意义:解耦请求与处理,将复杂请求按责任分割。
class Order 
{private double amount;Order(amount) => this.amount = amount;GetAmount()   => this.amount;
}// 不同的订单,不同的处理方式
abstract class OrderHandler 
{private OrderHandler next;// 处理不了,转发到下一个void SetNext(next) => this.next = next;abstract void Handle(order);
} // 普通员工处理订单
class Junior inherits OrderHandler
{override void Handle(order){   order.GetAmount() <= 500 ? Print("普通员工处理订单") : this.next.Handle(order);}
}// 高级员工处理订单
class Senior inherits OrderHandler
{override void Handle(order){order.GetAmount() <= 2000 ? Print("高级员工处理订单") : this.next.Handle(order);}
}// 经理员工处理订单
class Manager inherits OrderHandler
{override void Handle(order){order.GetAmount() <= 10000 ? Print("经理员工处理订单") : this.next.Handle(order);}
}void Client()
{junior  = new Junior ();senior  = new Senior ();manager = new Manager();junior.SetNext(senior );senior.SetNext(manager);order1 = new Order(300 );order2 = new Order(1500);order3 = new Order(3000);  // 客户端,处理不了的订单会转发junior.Handle(order1);junior.Handle(order2);junior.Handle(order3);
}

7,中介者模式(Mediator Pattern)

  • 内涵:使用一个中转平台,来协调多个对象之间的交互。
  • 意义:解耦对象的交互依赖,集中管理对象的交互逻辑。
// 中介者,可以注册用户,并向用户发送信息
interface IMediator : void Register(user), void Send(user, message);// 聊天室,充当用户的中介者
class ChatRoom implements IMediator
{private List<User> userList = new();void Register(user){userList.Add(user);// 注册用户,持有中介者user.SetMediator(this);}void Send(user, message){foreach (one in userList){  if (one != user){// 不是发送者的用户,会收到信息one.Receive(message);}}}
}class User
{private   string    name;protected IMediator mediator;User(name)                 => this.name     = name;void SetMediator(mediator) => this.mediator = mediator;// 用户将自己与信息,发给中介者,来转发信息void Send(message)         => this.mediator.Send(this, message);// 用户收到,中介者发来的信息void Receive(message)      => Print("{this.name}, 接收到信息,{message}");
}void Client()
{chatRoom = new ChatRoom(); laoWang  = new user("老王");xiaoLi   = new user("小李");chatRoom.Register(laoWang);chatRoom.Register(xiaoLi);laoWang.Send("来自老王向大家的问候");xiaoLi .Send("来自小李向大家的问候");
}

8,迭代器模式(Iterator Pattern)

  • 内涵:实现遍历接口,顺序访问集合对象的每个元素。
  • 意义:统一遍历形式,隐藏不同集合对象的内部结构。
interface IIterator : bool HasNext(), int Next();class Lottery
{private int[] nums = { 1, 2, 3, 4, 5, 6, 7 };// 返回彩票迭代器 IIterator CreateIterator() => new Iterator(nums);// 实现彩票迭代器private class Iterator implements IIterator{private int   index = -1;private int[] nums;Iterator(nums) => this.nums = nums;bool HasNext() => index < this.nums.Count;int  Next   () => this.nums[++index];}
}void Client()
{lottery  = new Lottery();iterator = lottery.CreateIterator();// 客户端,遍历彩票号码while (iterator.HasNext()){Print(iterator.Next());}
}

9,访问者模式(Visitor Pattern)

  • 内涵:将对对象的操作算法,转移到访问者中去实现。
  • 意义:分离对象的结构与操作,便于实现不同的操作。
// 智能电灯、智能插座,可以被不同的访问者操控
interface IVisitor
{void Visit(smartLight);void Visit(smartPlug);
}// 智能产品,可以被访问者操控
interface ISmart : void Accept(visitor);class SmartLight implements ISmart
{// 智能电灯,接受访问者的操控void Accept(visitor) => visitor.Visit(this);void GetInfo()       => Print("这是智能电灯");
}class SmartPlug implements ISmart
{// 智能插座,接受访问者的操控void Accept(visitor) => visitor.Visit(this);void GetInfo()       => Print("这是智能插座");
}// 智能家,可以操控智能产品
class SmartHome implements IVisitor
{// 必须要,智能电灯接受,才能访问void Visit(smartLight) => smartLight.GetInfo();// 必须要,智能插座接受,才能访问void Visit(smartPlug)  => smartPlug .GetInfo();
}// 家智能访问者,可以操控智能产品
class HomeAI implements IVisitor
{// 必须要,智能电灯接受,才能访问void Visit(smartLight) => Print("人工智能接管电灯");// 必须要,智能插座接受,才能访问void Visit(smartPlug)  => Print("人工智能接管插座");
}void Client()
{smartLight = new SmartLight();smartPlug  = new SmartPlug ();// 客户端,通过智能家,控制智能产品smartHome = new SmartHome();smartLight.Accept(smartHome);smartPlug .Accept(smartHome);// 客户端,通过家智能,控制智能产品homeAI = new HomeAI();smartLight.Accept(homeAI);smartPlug .Accept(homeAI);
}

注意:

  • 与策略相比,访问者实现不同操作,依赖于对象的数据结构,策略实现不同行为,独立于对象的数据结构。
  • 与命令相比,访问者是对象选择对自身的操作,操作与对象有关,命令是对象选择对请求的执行,执行与对象无关。

10,解释器模式(Interpreter Pattern)

  • 内涵:将语法抽象为表达式,嵌套组合表达式并解释出结果。
  • 意义:分离语法规则与解释逻辑,分解复杂规则为简单逻辑。
// 可以解释的表达式,参数是上下文信息
interface IExpression : int Interpret(ctxDict);// 字符表达式(终结符表达式)
class StrExpression implements IExpression
{private string str;StrExpression(str) => this.str = str;// 通过上下文,将字符解释为数字int Interpret(ctxDict) => ctxDict[str];
}// 乘法表达式(非终结符表达式)
class MulExpression implements IExpression
{private IExpression left;private IExpression right;MulExpression(left, right) => this.left = left, this.right = right;// 通过上下文,将左右表达式,解释为乘法int Interpret(ctxDict) => left.Interpret(ctxDict) * right.Interpret(ctxDict);
}// 除法表达式(非终结符表达式)
class DivExpression implements IExpression
{private IExpression left;private IExpression right;DivExpression(left, right) => this.left = left, this.right = right;// 通过上下文,将左右表达式,解释为除法int Interpret(ctxDict) => left.Interpret(ctxDict) / right.Interpret(ctxDict);
}void Client()
{// 解释器的上下文信息ctxDict = new Dictionary<string, int>{["a"] = 11,["b"] = 22,["c"] = 33,};// 表达式树(a * b / c)expression = new DivExpression(new MulExpression(new StrExpression("a"),new StrExpression("b")),new StrExpression("c"));// 客户端,根据上下文,解释表达式为(11 * 22 / 33),并计算出j俄国result = expression.Interpret(ctxDict);
}

11,备忘录模式(Memento Pattern)

  • 内涵:备份与恢复对象的状态。
  • 意义:实现撤销与回滚的操作。
// 备忘录对象,可以保存状态
class Memento
{private string state;// 备忘状态Memento(state)    => this.state = state;// 获取状态string GetState() => this.state;
}// 存储备忘录对象
class Taker
{private static Dictionary<string, Memento> mtDict = new();// 保存备忘对象AddMemento(name, memento) => this.mtDict[name] = memento;// 获取备忘对象GetMemento(name)          => this.mtDict[name];
}// 内存状态可以备份与恢复
class Memory
{private string state;SetState    (state)   => this.state = state;// 备份内存状态,到备忘录对象BackupState ()        => new Memento(state);// 恢复内存状态,从备忘录对象RestoreState(memento) =>  this.state = memento.GetState();
}void Client()
{memory = new Memory();taker  = new Taker();memory.SetState("## 要死不活状态 ##");// 备忘die状态taker.AddMemento("die", memory.BackupState());memory.SetState("hell", "## 生不如死状态 ##");// 备忘hell状态taker.AddMemento(memory.BackupState());// 客户端,决定还是回到die状态memory.RestoreState(taker.GetMemento("die"));
}

12,空对象模式(Null Object Pattern)

  • 内涵:用空对象,代替空值或无法操作。
  • 意义:避免检查,无效或无意义的结果。
interface ILogger : void Log(message);class RealLogger implements ILogger : void Log(message) => Print("记录日志:{message}");
class NullLogger implements ILogger : void Log(message) => Print("没有记录器");class LoggerFactory
{static ILogger Get(type){if (type == "File" || type == "Console"){return new RealLogger();}else{return new NullLogger();}}
}void Client()
{LoggerFactory.Get("File").log();// 客户端,不需要检查对象是否nullLoggerFactory.Get("FFFF").log(); 
}

设计模式的意义

主要在于两个层面:一个是形式上具有通用性复用性,一个是功能上具有抽象性封装性,并且后者支撑了前者。

更进一步,抽象性可以保证封装性,而达成这两者,就可以阻断或减少耦合性,即实现解耦——因为,紧密复杂的耦合性,总是发生在抽象不本质封装不严密的时候。

但,为什么要追求解耦呢?

因为人脑的算力有限,需要降低理解难度(搞不清步骤)与心智负担(记不住步骤),也就是降低系统复杂性,方能有效处理代码结构的逻辑关系。

那么,其效用就在于——获得代码系统的稳定性健壮性效率性可扩展性可维护性可替换性

所以,最佳的设计模式,是将可以系统、模块、功能等,彻底抽象封装成一个“黑盒”——可以“闭眼调用”,就像我们使用大脑,并不需要了解脑科学的神经运作原理一样,这是演化算法的抽象封装,或说是演化的设计模式

更多的设计模式

以上展示的设计模式,几乎代表了基础常用的全部,在此之上可以进行——组合搭配、细化改进与丰富增强,甚至创新创造,从而应对不同的业务模型,比如以下7种:

1,基于单例模式、工厂模式、代理模式——实现“延迟初始化模式”(Lazy initialization Pattern),即:初次使用时初始化。

2,基于单例模式 + 工厂模式——实现“多例模式”(Multiton Pattern),即:工厂产生多个单例。

3,基于装饰器模式——实现“资源自动化模式”(Resource Acquisition is Initialization,RAII),即:资源自动初始化与释放。

4,基于责任链模式——实现“委托模式”(Delegation Pattern),即:实际功能委托给其它对象处理。

5,基于责任链模式 + 外观模式——实现“双继承模式”(Twin Pattern),即:两个子对象组合在一起,就像继承了两个父类(外观提供),而一个对象没有的功能,就转发给另一个对象处理(责任链提供)。

6,基于桥接模式 + 外观模式——实现“服务模式”(Servant Pattern),即:为接口对象实现统一的新功能(桥接提供),传入接口对象,就可以获得新功能的服务(外观提供),而不必每个对象各自实现。

7,基于解释器模式 + 过滤器模式——实现“规范模式”(Specification Pattern),即:根据规则组合,进行逻辑判断(解释器提供),实现过滤查询(过滤器提供)。

还有一些过于“轻量”,一看就了解,如:

  • “流畅接口模式”(Fluent Interface Pattern)——就是“链式调用”。
  • “标记接口模式”(Marker Interface Pattern)——就是“元数据声明”。
  • “模块化模式”(Module Pattern )——就是“代码命名空间”。

更多模式可以参看:维基百科Software Design Pattern,很多基础模式来自经典书籍:维基百科《GoF Design Patterns》——注意,本文示例总结,并未参考这两处内容,但这两个链接提供了丰富的相关资料,可作为补充查阅。

结语

事实上,一旦熟悉掌握融会贯通,就会发现设计模式之于编程,是无法绕过的无处不在——除非,机器生成、尽情冗余、无人阅读。

然而,代码设计模式,只是对领域与业务的抽象建模,显然不同的领域与业务会千差万别,尽管基础模式具有一定的通用性,但也不可能全面覆盖,所以随着环境情况的变化实践,一定会有适应不同需求的设计模式,不断被发明应用

那么,在基本层面与底层方向上,不同的视角抽象,也会有不同的理解建模——所有的模型都是错的,只是有些是有用的——因此,已有的所有设计模式,也并非是唯一解最优解,而只是某个解某种解

至于,是否存在“万金油模式”——从抽象封装角度来看,是几乎没有的,但从演化角度来看,是可能存在的,即基于迭代试错的“最优解”

从某种角度说,人脑设计基于抽象封装——是静态的一事一议,自然演化基于迭代试错——是动态的适应塑造,而后者的动态性就在于贯穿生命体,从微观到宏观的3种基本适应模式,即:正反馈模式、负反馈模式、一致性与非一致性前馈模式——关键词,就是动态性可塑性适应性

事实上,演化是宇宙中唯一的“成功学”——这是终极的编码模式,而这样的“演化代码”,是“活的”而不是“死的”

最后,我们需要超越这些设计模式,而不是死记硬套这些设计模式,要看到这些设计模式的适用性与局限性,而不是拿着这些设计模式的“锤子”看什么都是“钉子”——最终就会,从前看它们很高级,现在看它们就那样,未来看它们啥也不是……这才是全新的开始。

欢迎关注我的知乎专栏:「又在写代码」与「闪念与认知」以及知乎账号(可交流沟通,这里不看也不回复)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/47608.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Yolov8网络结构学习

详解YOLOv8网络结构/环境搭建/数据集获取/训练/推理/验证/导出/部署 深入解析YOLOv8&#xff1a;网络结构与推理过程 YOLO? You Know! --YOLOV8详解 一&#xff1a;yolov8总体结构 1.Backbone:它采用了一系列卷积和 反卷积层只来提取特征&#xff0c;同时也使用了残差连接和…

C# —— HashTable

集合collections命名空间&#xff0c;专门进行一系列的数据存储和检索的类&#xff0c;主要包含了:堆栈、和队列、list、ArrayList、数组 HashTable 字典 storeList 排序列表等类 Array 数组 长度固定&#xff0c; 类型固定 通过索引值来进行访问 ArrayList动态数组&#xff0c…

网站开发:使用VScode安装yarn包和运行前端项目

一、首先打开PowerShell-管理员身份运行ISE 输入命令&#xff1a; set-ExecutionPolicy RemoteSigned 选择“全是”&#xff0c;表示允许在本地计算机上运行由本地用户创建的脚本&#xff0c;没有报错就行了 二、接着打开VScode集成终端 输入 npm install -g yarn 再次输入以…

小程序-3(页面导航+页面事件+生命周期+WXS)

目录 1.页面导航 声明式导航 导航到tabBar页面 导航到非tabBar页面 后退导航 编程式导航 后退导航 导航传参 声明式导航传参 编程式导航传参 在onload中接收导航参数 2.页面事件 下拉刷新 停止下拉刷新的效果 ​编辑 上拉触底 配置上拉触底距离 上拉触底的节…

js补环境系列之剖析:原型、原型对象、实例对象三者互相转化(不讲废话、全是干货)

【作者主页】&#xff1a;小鱼神1024 【擅长领域】&#xff1a;JS逆向、小程序逆向、AST还原、验证码突防、Python开发、浏览器插件开发、React前端开发、NestJS后端开发等等 思考下&#xff1a;js补环境中&#xff0c;什么场景会用到原型、原型对象、实例对象&#xff1f; 举…

【前端异步问题】通过Promise.all()解决异步取值问题

场景 有一个对象数组itemList,数组中的对象有的有属性attr,有的没有。没有属性a的对象需要通过调用接口获取并赋值给相应对象。 再将处理完后的对象数组&#xff0c;传入另一个接口中。 let itemList [{ id: 0, attr: 雨伞},{ id: 1, attr: null},{ id: 2, attr: 水杯},{ id: …

【用户投稿】使用 SeaTunnel 进行 HTTP 同步到 Doris 实战经验分享

需求背景 由于我司的项目中需要接入不同的数据源的数据到数仓中&#xff0c;在选择了众多的产品中最后选择了Apache SeaTunnel&#xff0c;对比参考 目前我这边使用的接口&#xff0c;暂时没有接口认证&#xff0c;如果需要接口认证的方式接入数据&#xff0c;再做讨论及测试…

谈谈大数据采集和常见问题

01 什么是数据采集 数据采集是大数据的基石&#xff0c;不论是现在的互联网公司&#xff0c;物联网公司或者传统的IT公司&#xff0c;每个业务流程环节都会产生大量的数据&#xff0c;同时用户操作的日志也会产生大量的数据&#xff0c;为了将这些结构化和非结构化的数据进行…

[C/C++入门][for]24、菲波那契数列

斐波那契数列是数学中的一个经典数列&#xff0c;以其独特的递归性质而闻名。 数列的前两项通常是0和1&#xff08;或者有时从1开始&#xff0c;当然这个不是强制要求&#xff09;&#xff0c;之后的每一项都是前两项的和。数列的前几项如下所示&#xff1a; 0, 1, 1, 2, 3, …

docker网络互联

最近学习docker的时候发现多了很多网卡&#xff0c;这些似乎都和docker有关&#xff0c;所以我便往下深入了解了一番&#xff1b; 一、docker网卡 docker 0是安装 docker 的时候生成的虚拟网桥&#xff0c;它在内核层连通了其他物理或者虚拟网卡&#xff0c;这就可以将所…

AI发展下的伦理挑战,应当如何应对?

AI发展下的伦理挑战&#xff0c;应当如何应对&#xff1f; 人工智能飞速发展的同时&#xff0c;也逐渐暴露出侵犯数据隐私、制造“信息茧房”等种种伦理风险。随着AI技术在社会各个领域的广泛应用&#xff0c;关于AI伦理和隐私保护问题日趋凸显。尽管国外已出台系列法规来规范…

常用优秀内网穿透工具(实测详细版)

文章目录 1、前言2、安装Nginx3、配置Nginx4、启动Nginx服务4.1、配置登录页面 5、内网穿透5.1、cpolar5.1.1、cpolar软件安装5.1.2、cpolar穿透 5.2、Ngrok5.2.1、Ngrok安装5.2.2、随机域名5.2.3、固定域名5.2.4、前后端服务端口 5.3、NatApp5.4、Frp5.4.1、下载Frp5.4.2、暴露…

自动发卡机器人来看:生成式AI的未来,是聊天还是代理?

引言 今天我们要聊聊一个有趣的话题&#xff1a;生成式AI的未来究竟是在聊天系统&#xff08;Chat&#xff09;中展现智慧&#xff0c;还是在自主代理&#xff08;Agent&#xff09;中体现能力&#xff1f; 一、生成式AI&#xff0c;你是谁&#xff1f; 首先&#xff0c;生成…

【数据结构】--- 栈和队列

前言 前面学习了数据结构的顺序表、单链表、双向循环链表这些结构&#xff1b;现在就来学习栈和队列&#xff0c;这里可以简单的说栈和队列是具有特殊化的线性表 一、栈 1.1、栈的概念和结构 栈是一种遵循先入后出逻辑的线性数据结构。 栈是一种特殊的线性表&#xff0c;它只允…

vivado FFT IP Core

文章目录 前言FFT IP 接口介绍接口简介tdata 格式说明 其他细节关于计算精度及缩放系数计算溢出架构选择数据顺序实时/非实时模式数据输入输出时序关于配置信息的应用时间节点 FFT IP 例化介绍控制代码实现 & 测试参考文献 前言 由于计算资源受限&#xff0c;准备将上位机 …

【漏洞复现】泛微E-Cology WorkflowServiceXml SQL注入漏洞

0x01 产品简介 泛微e-cology是一款由泛微网络科技开发的协同管理平台&#xff0c;支持人力资源、财务、行政等多功能管理和移动办公。 0x02 漏洞概述 泛微OAE-Cology 接口/services/WorkflowServiceXml 存在SQL注入漏洞&#xff0c;可获取数据库权限&#xff0c;导致数据泄露…

Qt日志库QsLog使用教程

前言 最近项目中需要用到日志库。上一次项目中用到了log4qt库&#xff0c;这个库有个麻烦的点是要配置config文件&#xff0c;所以这次切换到了QsLog。用了后这个库的感受是&#xff0c;比较轻量级&#xff0c;嘎嘎好用&#xff0c;推荐一波。 下载QsLog库 https://github.c…

【踩坑日记】【教程】嵌入式 Linux 通过 nfs 下载出现 T T T T [Retry count exceeded: starting again]

文章目录 1 本篇文章解决的问题2 问题解决原理3 问题环境4 开启 ubuntu-20.04 的 nfs24.1 确认 nfs2 是否已经开启4.2 开启 nfs2 5 卸载 iptables5.1 卸载 iptables5.2 禁用 ufw5.3 尝试重新下载 6 原理分析6.1 nfs2 开启部分6.2 卸载 iptables 部分 7 后记7.1 拓扑结构一7.2 拓…

生成Elasticsearch xpack安全认证证书

首次启动 Elasticsearch 时&#xff0c;会为用户生成密码&#xff0c;并自动为用户配置 TLS &#xff0c;可以随时调整 TLS 配置&#xff0c;更新节点证书 一、生成证书 1、在任意节点上进入 Elasticsearch 的安装目录&#xff0c;使用 elasticsearch-certutil 为集群生成 CA…

【博士每天一篇文献-算法】连续学习算法之HNet:Continual learning with hypernetworks

阅读时间&#xff1a;2023-12-26 1 介绍 年份&#xff1a;2019 作者&#xff1a;Johannes von Oswald&#xff0c;Google Research&#xff1b;Christian Henning&#xff0c;EthonAI AG&#xff1b;Benjamin F. Grewe&#xff0c;苏黎世联邦理工学院神经信息学研究所 期刊&a…