首页 > 其他分享 >23种设计模式笔记-结构型模式

23种设计模式笔记-结构型模式

时间:2024-05-08 16:23:18浏览次数:28  
标签:std struct 23 composite void Component operation 设计模式 结构型

23种设计模式-结构型模式

笔记模板

模式

  • 前提 - 模式:
  • 概念:
  • 规则:
  • 实现细节:
  • 应用场景:
  • 示意图:
  • 代码实现:

创建型模式

  • 适配器、桥接、组合、装饰、外观、享元、代理。

适配器模式 - 接口兼容思想

  • 概念: 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作(核心:适配器)

  • 规则: 通过一个类,实现从调用者(客户端)到被调用者(服务端)的接口实现

  • 实现细节: 其分为对象适配器和类适配器,对象适配器其功能为接口的转换(一对一,即单一继承),类适配器为多重继承,即继承了不同类的产物,可以更好的封装适配器(多对多,即多重继承)
    客户端接口 ---适配器--- 服务端实现;
    实现时需要注意,使用构造函数/调用方法传递的方式实现服务对象的引用;
    实现方法以客户端接口为准,即使用服务端实现完成对客户端接口的适配

  • 应用场景: 1.使用类,但是其接口与其他代码不兼容;2.复用属于同一个继承体系,但是存在额外共性的类。这些额外共性可以使用适配器实现(类似于装饰器);操作系统本质就是一种适配器,按其标准实现了对硬件的封装,从而使上层的软件能够以标准接口,如POSIX等,实现对其的调用。

  • 示意图:
    对象适配器:
    image
    类适配器
    image

  • 代码实现:

    c++
    //对象适配器
    /**
     * The Target defines the domain-specific interface used by the client code.
     */
    class Target {
     public:
      virtual ~Target() = default;
    
      virtual std::string Request() const {
    	return "Target: The default target's behavior.";
      }
    };
    
    /**
     * The Adaptee contains some useful behavior, but its interface is incompatible
     * with the existing client code. The Adaptee needs some adaptation before the
     * client code can use it.
     */
    class Adaptee {
     public:
      std::string SpecificRequest() const {
    	return ".eetpadA eht fo roivaheb laicepS";
      }
    };
    
    /**
     * The Adapter makes the Adaptee's interface compatible with the Target's
     * interface.
     */
    class Adapter : public Target {
     private:
      Adaptee *adaptee_;
    
     public:
      Adapter(Adaptee *adaptee) : adaptee_(adaptee) {}
      std::string Request() const override {
    	std::string to_reverse = this->adaptee_->SpecificRequest();
    	std::reverse(to_reverse.begin(), to_reverse.end());
    	return "Adapter: (TRANSLATED) " + to_reverse;
      }
    };
    
    /**
     * The client code supports all classes that follow the Target interface.
     */
    void ClientCode(const Target *target) {
      std::cout << target->Request();
    }
    
    int main() {
      std::cout << "Client: I can work just fine with the Target objects:\n";
      Target *target = new Target;
      ClientCode(target);
      std::cout << "\n\n";
      Adaptee *adaptee = new Adaptee;
      std::cout << "Client: The Adaptee class has a weird interface. See, I don't understand it:\n";
      std::cout << "Adaptee: " << adaptee->SpecificRequest();
      std::cout << "\n\n";
      std::cout << "Client: But I can work with it via the Adapter:\n";
      Adapter *adapter = new Adapter(adaptee);
      ClientCode(adapter);
      std::cout << "\n";
    
      delete target;
      delete adaptee;
      delete adapter;
    
      return 0;
    }
    
    //多重继承
    /**
     * The Target defines the domain-specific interface used by the client code.
     */
    class Target {
     public:
      virtual ~Target() = default;
      virtual std::string Request() const {
    	return "Target: The default target's behavior.";
      }
    };
    
    /**
     * The Adaptee contains some useful behavior, but its interface is incompatible
     * with the existing client code. The Adaptee needs some adaptation before the
     * client code can use it.
     */
    class Adaptee {
     public:
      std::string SpecificRequest() const {
    	return ".eetpadA eht fo roivaheb laicepS";
      }
    };
    
    /**
     * The Adapter makes the Adaptee's interface compatible with the Target's
     * interface using multiple inheritance.
     */
    class Adapter : public Target, public Adaptee {
     public:
      Adapter() {}
      std::string Request() const override {
    	std::string to_reverse = SpecificRequest();
    	std::reverse(to_reverse.begin(), to_reverse.end());
    	return "Adapter: (TRANSLATED) " + to_reverse;
      }
    };
    
    /**
     * The client code supports all classes that follow the Target interface.
     */
    void ClientCode(const Target *target) {
      std::cout << target->Request();
    }
    
    int main() {
      std::cout << "Client: I can work just fine with the Target objects:\n";
      Target *target = new Target;
      ClientCode(target);
      std::cout << "\n\n";
      Adaptee *adaptee = new Adaptee;
      std::cout << "Client: The Adaptee class has a weird interface. See, I don't understand it:\n";
      std::cout << "Adaptee: " << adaptee->SpecificRequest();
      std::cout << "\n\n";
      std::cout << "Client: But I can work with it via the Adapter:\n";
      Adapter *adapter = new Adapter;
      ClientCode(adapter);
      std::cout << "\n";
    
      delete target;
      delete adaptee;
      delete adapter;
    
      return 0;
    }
    
    c
    #include <stdio.h>
    #include <stdlib.h>
    
    // 定义适配者接口
    struct adaptee {
    	void (*specificRequest)(void);
    };
    
    // 适配者操作
    void adaptee_specificRequest(void)
    {
    	printf("adaptee specific request\n");
    }
    
    // 初始化适配者
    struct adaptee* adaptee_create(void)
    {
    	struct adaptee* adaptee = (struct adaptee *)malloc(sizeof(struct adaptee *));
    	adaptee->specificRequest = adaptee_specificRequest;
    	return adaptee;
    }
    
    typedef struct adapter adapter;
    
    // 定义目标接口
    struct target {
    	void (*request)(struct adapter* this);
    };
    
    // 定义适配器
    struct adapter {
    	struct adaptee* adaptee;
    	struct target target;
    };
    
    // 适配器请求操作
    void adapter_request(struct adapter* this)
    {
    	printf("adapter request\n");
    	this->adaptee->specificRequest();
    }
    
    // 初始化适配器
    struct adapter* adapter_create(struct adaptee* adaptee)
    {
    	struct adapter* adapter = (struct adapter *)malloc(sizeof(struct adapter *));
    	adapter->target.request = (void (*)())adapter_request;
    	adapter->adaptee = adaptee;
    	return adapter;
    }
    
    int main() {
    	// 创建适配者
    	struct adaptee* adaptee = adaptee_create();
    
    	// 创建适配器,并使用适配者初始化
    	struct adapter* adapter = adapter_create(adaptee);
    
    	// 调用适配器的请求方法
    	adapter->target.request(adapter);
    
    	// 释放内存
    	free(adapter);
    	free(adaptee);
    
    	return 0;
    }
    

桥接模式 - 对复杂系统的分离

  • 前提 - 抽象工厂模式、适配器模式: 桥接模式中的抽象方/实现方的实现可以使用抽象工厂模式,适配器可以对特定的实现

  • 概念: 将抽象部分与它的实现部分分离,使它们都可以独立地变化。(核心是避免子类数量的爆炸)

  • 规则: 使用组合的方式,实现对类之间的自由组合,从而降低了子类的数量(适用于开发过程中的实现),核心是降低耦合度

  • 实现细节: 抽象部分(GUI)其实现了控制程序的外观、实现部分(API)采用标准的API,实现了对多种操作系统的适配、而GUI和API之间使用了桥接模式进行适配;UNIX标准输入输出,如POSIX就是作为一个桥接器存在的。LINUX的各种子系统类似于这个关系,其充当了硬件实现(驱动)和软件抽象(API)的桥接
    核心是在设计之前解耦维度,实现维度的独立性;同时,实现多层次的抽象

  • 应用场景:1.拆分或者重组复杂类(对复杂代码进行解耦);2.在多个维度上对原有类进行扩展;3.需要在运行时切换不同的实现方法

  • 示意图:
    image

  • 代码实现:

    c++
    /**
     * The Implementation defines the interface for all implementation classes. It
     * doesn't have to match the Abstraction's interface. In fact, the two
     * interfaces can be entirely different. Typically the Implementation interface
     * provides only primitive operations, while the Abstraction defines higher-
     * level operations based on those primitives.
     */
    
    class Implementation {
     public:
      virtual ~Implementation() {}
      virtual std::string OperationImplementation() const = 0;
    };
    
    /**
     * Each Concrete Implementation corresponds to a specific platform and
     * implements the Implementation interface using that platform's API.
     */
    class ConcreteImplementationA : public Implementation {
     public:
      std::string OperationImplementation() const override {
    	return "ConcreteImplementationA: Here's the result on the platform A.\n";
      }
    };
    class ConcreteImplementationB : public Implementation {
     public:
      std::string OperationImplementation() const override {
    	return "ConcreteImplementationB: Here's the result on the platform B.\n";
      }
    };
    
    /**
     * The Abstraction defines the interface for the "control" part of the two class
     * hierarchies. It maintains a reference to an object of the Implementation
     * hierarchy and delegates all of the real work to this object.
     */
    
    class Abstraction {
      /**
       * @var Implementation
       */
     protected:
      Implementation* implementation_;
    
     public:
      Abstraction(Implementation* implementation) : implementation_(implementation) {
      }
    
      virtual ~Abstraction() {
      }
    
      virtual std::string Operation() const {
    	return "Abstraction: Base operation with:\n" +
    		   this->implementation_->OperationImplementation();
      }
    };
    /**
     * You can extend the Abstraction without changing the Implementation classes.
     */
    class ExtendedAbstraction : public Abstraction {
     public:
      ExtendedAbstraction(Implementation* implementation) : Abstraction(implementation) {
      }
      std::string Operation() const override {
    	return "ExtendedAbstraction: Extended operation with:\n" +
    		   this->implementation_->OperationImplementation();
      }
    };
    
    /**
     * Except for the initialization phase, where an Abstraction object gets linked
     * with a specific Implementation object, the client code should only depend on
     * the Abstraction class. This way the client code can support any abstraction-
     * implementation combination.
     */
    void ClientCode(const Abstraction& abstraction) {
      // ...
      std::cout << abstraction.Operation();
      // ...
    }
    /**
     * The client code should be able to work with any pre-configured abstraction-
     * implementation combination.
     */
    
    int main() {
      Implementation* implementation = new ConcreteImplementationA;
      Abstraction* abstraction = new Abstraction(implementation);
      ClientCode(*abstraction);
      std::cout << std::endl;
      delete implementation;
      delete abstraction;
    
      implementation = new ConcreteImplementationB;
      abstraction = new ExtendedAbstraction(implementation);
      ClientCode(*abstraction);
    
      delete implementation;
      delete abstraction;
    
      return 0;
    }
    
    c
    #include <stdio.h>
    
    // 实现方接口
    typedef struct {
    	void (*implement)(void);
    } Implementation;
    
    // 具体实现类A
    void implementA(void) {
    	printf("Implementation A method\n");
    }
    
    // 具体实现类B
    void implementB(void) {
    	printf("Implementation B method\n");
    }
    
    // 抽象方接口
    typedef struct {
    	void (*abstractionOperation)(void);
    	Implementation *implementation;
    } Abstraction;
    
    // 抽象方实现A
    void abstractionAMethod(Abstraction *abstraction) {
    	printf("Abstraction A method\n");
    	abstraction->implementation->implement();
    }
    
    // 抽象方实现B
    void abstractionBMethod(Abstraction *abstraction) {
    	printf("Abstraction B method\n");
    	abstraction->implementation->implement();
    }
    
    int main() {
    	Implementation implementationA = {implementA};
    	Implementation implementationB = {implementB};
    
    	Abstraction abstractionA = {abstractionAMethod, &implementationA};
    	Abstraction abstractionB = {abstractionBMethod, &implementationB};
    
    	abstractionA.abstractionOperation(&abstractionA);
    	abstractionB.abstractionOperation(&abstractionB);
    
    	return 0;
    }
    

组合模式 - 树形的层级结构,降低系统的复杂度

  • 概念: 将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性

  • 规则: 对与产品-盒子交互策略来说,需要设计一个通用接口逐级实现所需要功能,其核心思想是降低耦合度,即上层只需要调用相应接口,下层递归实现即可

  • 实现细节: 对于每个产品(叶子节点)而言,其实现了对应的工作(最简单的工作);而对于盒子(子根结点)而言,其作用是对操作进行分发与组合,以实现产品的结合;而对于组件(通用接口)而言,其需要实现对于操作(方法)的抽象,从而提供给产品和盒子。该种模式应用与前端显示组件的编写上,如LVGL、AWTK等,其在绘制时,使用了树形结构进行逐层调用与绘制

  • 应用场景: 实现树状对象结构;客户端能够以相同方式处理简单和复杂元素

  • 示意图:
    image

  • 代码实现:

    c++
    #include <algorithm>
    #include <iostream>
    #include <list>
    #include <string>
    /**
     * The base Component class declares common operations for both simple and
     * complex objects of a composition.
     */
    class Component {
      /**
       * @var Component
       */
     protected:
      Component *parent_;
      /**
       * Optionally, the base Component can declare an interface for setting and
       * accessing a parent of the component in a tree structure. It can also
       * provide some default implementation for these methods.
       */
     public:
      virtual ~Component() {}
      void SetParent(Component *parent) {
    	this->parent_ = parent;
      }
      Component *GetParent() const {
    	return this->parent_;
      }
      /**
       * In some cases, it would be beneficial to define the child-management
       * operations right in the base Component class. This way, you won't need to
       * expose any concrete component classes to the client code, even during the
       * object tree assembly. The downside is that these methods will be empty for
       * the leaf-level components.
       */
      virtual void Add(Component *component) {}
      virtual void Remove(Component *component) {}
      /**
       * You can provide a method that lets the client code figure out whether a
       * component can bear children.
       */
      virtual bool IsComposite() const {
    	return false;
      }
      /**
       * The base Component may implement some default behavior or leave it to
       * concrete classes (by declaring the method containing the behavior as
       * "abstract").
       */
      virtual std::string Operation() const = 0;
    };
    /**
     * The Leaf class represents the end objects of a composition. A leaf can't have
     * any children.
     *
     * Usually, it's the Leaf objects that do the actual work, whereas Composite
     * objects only delegate to their sub-components.
     */
    class Leaf : public Component {
     public:
      std::string Operation() const override {
    	return "Leaf";
      }
    };
    /**
     * The Composite class represents the complex components that may have children.
     * Usually, the Composite objects delegate the actual work to their children and
     * then "sum-up" the result.
     */
    class Composite : public Component {
      /**
       * @var \SplObjectStorage
       */
     protected:
      std::list<Component *> children_;
    
     public:
      /**
       * A composite object can add or remove other components (both simple or
       * complex) to or from its child list.
       */
      void Add(Component *component) override {
    	this->children_.push_back(component);
    	component->SetParent(this);
      }
      /**
       * Have in mind that this method removes the pointer to the list but doesn't
       * frees the
       *     memory, you should do it manually or better use smart pointers.
       */
      void Remove(Component *component) override {
    	children_.remove(component);
    	component->SetParent(nullptr);
      }
      bool IsComposite() const override {
    	return true;
      }
      /**
       * The Composite executes its primary logic in a particular way. It traverses
       * recursively through all its children, collecting and summing their results.
       * Since the composite's children pass these calls to their children and so
       * forth, the whole object tree is traversed as a result.
       */
      std::string Operation() const override {
    	std::string result;
    	for (const Component *c : children_) {
    	  if (c == children_.back()) {
    		result += c->Operation();
    	  } else {
    		result += c->Operation() + "+";
    	  }
    	}
    	return "Branch(" + result + ")";
      }
    };
    /**
     * The client code works with all of the components via the base interface.
     */
    void ClientCode(Component *component) {
      // ...
      std::cout << "RESULT: " << component->Operation();
      // ...
    }
    
    /**
     * Thanks to the fact that the child-management operations are declared in the
     * base Component class, the client code can work with any component, simple or
     * complex, without depending on their concrete classes.
     */
    void ClientCode2(Component *component1, Component *component2) {
      // ...
      if (component1->IsComposite()) {
    	component1->Add(component2);
      }
      std::cout << "RESULT: " << component1->Operation();
      // ...
    }
    
    /**
     * This way the client code can support the simple leaf components...
     */
    
    int main() {
      Component *simple = new Leaf;
      std::cout << "Client: I've got a simple component:\n";
      ClientCode(simple);
      std::cout << "\n\n";
      /**
       * ...as well as the complex composites.
       */
    
      Component *tree = new Composite;
      Component *branch1 = new Composite;
    
      Component *leaf_1 = new Leaf;
      Component *leaf_2 = new Leaf;
      Component *leaf_3 = new Leaf;
      branch1->Add(leaf_1);
      branch1->Add(leaf_2);
      Component *branch2 = new Composite;
      branch2->Add(leaf_3);
      tree->Add(branch1);
      tree->Add(branch2);
      std::cout << "Client: Now I've got a composite tree:\n";
      ClientCode(tree);
      std::cout << "\n\n";
    
      std::cout << "Client: I don't need to check the components classes even when managing the tree:\n";
      ClientCode2(tree, simple);
      std::cout << "\n";
    
      delete simple;
      delete tree;
      delete branch1;
      delete branch2;
      delete leaf_1;
      delete leaf_2;
      delete leaf_3;
    
      return 0;
    }
    
    c
    #include <stdio.h>
    #include <stdlib.h>
    
    enum type{
    	LEAF = 1,
    	BRANCH,
    };
    // 定义组件接口
    typedef struct Component {
    	int value;
    	int type;
    	void (*operation)(struct Component *);
    } Component;
    
    // 定义叶子节点
    typedef struct Leaf {
    	Component base;
    } Leaf;
    
    void leaf_operation(Component *component) {
    	printf("Leaf: %d\n", component->value);
    }
    
    Leaf* leaf_create(int value) {
    	Leaf *leaf = (Leaf*)malloc(sizeof(Leaf));
    	leaf->base.value = value;
    	leaf->base.type = LEAF;
    	leaf->base.operation = leaf_operation;
    	return leaf;
    }
    
    // 定义组合节点
    typedef struct Composite {
    	Component base;
    	Component **children;
    	int num_children;
    } Composite;
    
    #define offsetof(s, m)      ((size_t)&(((s *)0)->m))
    #define container_of(ptr, type, member) \
    	((type *)((char *)(ptr) - offsetof(type, member)))
    
    void composite_operation(Component *component) {
    	Composite *composite = (Composite*)component;
    	printf("Composite: %d\n", component->value);
    
    	for (int i = 0; i < composite->num_children; i++) {
    		composite->children[i]->operation(composite->children[i]);
    	}
    }
    
    Composite* composite_create(int value, int num_children) {
    	Composite *composite = (Composite*)malloc(sizeof(Composite));
    	composite->base.value = value;
    	composite->base.type = BRANCH;
    	composite->base.operation = composite_operation;
    	composite->num_children = num_children;
    	composite->children = (Component**)malloc(sizeof(Component*) * num_children);
    	for (int i = 0; i < num_children; i++) {
    		composite->children[i] = NULL;
    	}
    	return composite;
    }
    
    void composite_add_child(Composite *composite, Component *child, int index) {
    	if (index < 0 || index >= composite->num_children) {
    		printf("Invalid index %d\n", index);
    		return;
    	}
    	composite->children[index] = child;
    }
    
    void composite_remove_child(Composite *composite, int index) {
    	if (index < 0 || index >= composite->num_children) {
    		printf("Invalid index %d\n", index);
    		return;
    	}
    	composite->children[index] = NULL;
    }
    
    void composite_free_unit(Composite *composite) {
    	if (!composite)
    		return;
    
    	if (composite->base.type == LEAF)
    		return;
    
    	for (int i = 0; i < composite->num_children; i++) {
    		if (composite->children[i]) {
    		composite_free_unit((struct Composite*)container_of(composite->children[i], struct Composite, base));
    		printf("free children[%d], value: %d\n", i, composite->children[i]->value);
    			free(composite->children[i]);
    		}
    	}
    
    	if (composite->children) {
    		free(composite->children);
    	}
    }
    
    void composite_free(Composite *composite) {
    	composite_free_unit(composite);
    	if (composite) {
    		free(composite);
    	}
    }
    int main() {
    	printf("create root and leaf\n");
    	// 创建根节点和叶子节点
    	Composite *root = composite_create(0, 3);
    	Leaf *leaf1 = leaf_create(1);
    	Leaf *leaf2 = leaf_create(2);
    
    	// 将叶子节点添加到根节点中
    	composite_add_child(root, &leaf1->base, 0);
    	composite_add_child(root, &leaf2->base, 1);
    
    	// 创建子节点并将其添加到根节点中
    	Composite *subtree = composite_create(3, 2);
    	Leaf *leaf3 = leaf_create(4);
    	Leaf *leaf4 = leaf_create(5);
    	composite_add_child(subtree, &leaf3->base, 0);
    	composite_add_child(subtree, &leaf4->base, 1);
    	composite_add_child(root, &subtree->base, 2);
    
    	// 执行操作
    	root->base.operation(&root->base);
    
    	printf("free root and leaf\n");
    	// 释放内存
    	composite_free(root);
    
    	return 0;
    }
    

装饰器模式 - 使对象和方法解耦,是桥接模式的另一种实现

  • 概念: 动态地给一个对象添加一些额外的职责。就增加功能来说,相比生成子类更为灵活;

  • 规则: 核心需求是防止需求的增加导致子类数量的爆炸;其核心方法是利用聚合/组合思想,实现封装器,而不是使用继承。封装器需要实现与封装对象相同的接口,从而使客户端可以对采用同一接口进行调用

  • 实现细节: 在客户端,客户需要将基础对象放入一系列装饰中,形成栈结构;在装饰器中,需要实现装饰基类以实现基础接口,同时,实现具体装饰类实现装饰所需的操作

  • 应用场景: 无需修改原始代码的情况下使用对象,并为对象添加额外的方法(行为);面向对象方法的扩展受到无法(难以)继承的限制;

  • 示意图:
    image

  • 代码实现:

    c++
    /**
     * The base Component interface defines operations that can be altered by
     * decorators.
     */
    class Component {
     public:
      virtual ~Component() {}
      virtual std::string Operation() const = 0;
    };
    /**
     * Concrete Components provide default implementations of the operations. There
     * might be several variations of these classes.
     */
    class ConcreteComponent : public Component {
     public:
      std::string Operation() const override {
    	return "ConcreteComponent";
      }
    };
    /**
     * The base Decorator class follows the same interface as the other components.
     * The primary purpose of this class is to define the wrapping interface for all
     * concrete decorators. The default implementation of the wrapping code might
     * include a field for storing a wrapped component and the means to initialize
     * it.
     */
    class Decorator : public Component {
      /**
       * @var Component
       */
     protected:
      Component* component_;
    
     public:
      Decorator(Component* component) : component_(component) {
      }
      /**
       * The Decorator delegates all work to the wrapped component.
       */
      std::string Operation() const override {
    	return this->component_->Operation();
      }
    };
    /**
     * Concrete Decorators call the wrapped object and alter its result in some way.
     */
    class ConcreteDecoratorA : public Decorator {
      /**
       * Decorators may call parent implementation of the operation, instead of
       * calling the wrapped object directly. This approach simplifies extension of
       * decorator classes.
       */
     public:
      ConcreteDecoratorA(Component* component) : Decorator(component) {
      }
      std::string Operation() const override {
    	return "ConcreteDecoratorA(" + Decorator::Operation() + ")";
      }
    };
    /**
     * Decorators can execute their behavior either before or after the call to a
     * wrapped object.
     */
    class ConcreteDecoratorB : public Decorator {
     public:
      ConcreteDecoratorB(Component* component) : Decorator(component) {
      }
    
      std::string Operation() const override {
    	return "ConcreteDecoratorB(" + Decorator::Operation() + ")";
      }
    };
    /**
     * The client code works with all objects using the Component interface. This
     * way it can stay independent of the concrete classes of components it works
     * with.
     */
    void ClientCode(Component* component) {
      // ...
      std::cout << "RESULT: " << component->Operation();
      // ...
    }
    
    int main() {
      /**
       * This way the client code can support both simple components...
       */
      Component* simple = new ConcreteComponent;
      std::cout << "Client: I've got a simple component:\n";
      ClientCode(simple);
      std::cout << "\n\n";
      /**
       * ...as well as decorated ones.
       *
       * Note how decorators can wrap not only simple components but the other
       * decorators as well.
       */
      Component* decorator1 = new ConcreteDecoratorA(simple);
      Component* decorator2 = new ConcreteDecoratorB(decorator1);
      std::cout << "Client: Now I've got a decorated component:\n";
      ClientCode(decorator2);
      std::cout << "\n";
    
      delete simple;
      delete decorator1;
      delete decorator2;
    
      return 0;
    }
    
    c
    #include <stdio.h>
    #include <stdlib.h>
    
    // 被装饰者抽象接口Component
    typedef struct Component {
    	void (*operation)(struct Component *);
    } Component;
    
    // 被装饰者具体实现ConcreteComponent
    typedef struct ConcreteComponent {
    	Component base;
    } ConcreteComponent;
    
    // 具体的被装饰者实现的操作
    void concrete_operation(Component *self) {
    	printf("Concrete operation\n");
    }
    
    // 装饰者基类
    typedef struct Decorator {
    	Component base;
    	Component *decorated;
    } Decorator;
    
    // 装饰者的操作实现
    void decorator_operation(Component *self) {
    	Decorator *decorator = (Decorator *)self;
    	decorator->decorated->operation(decorator->decorated);
    }
    
    // 具体的装饰者A实现
    typedef struct ConcreteDecoratorA {
    	Decorator base;
    } ConcreteDecoratorA;
    
    // 装饰者A装饰的功能实现
    void decorator_a_operation(Component *self)
    {
    	printf("Excuting decoratorA operation.\n");
    
    	//调用父类方法
    	decorator_operation(self);
    }
    
    // 具体的装饰者B实现
    typedef struct ConcreteDecoratorB {
    	Decorator base;
    } ConcreteDecoratorB;
    
    // 装饰者B装饰的功能实现
    void decorator_b_operation(Component *self)
    {
    	printf("Excuting decoratorB operation.\n");
    
    	//调用父类方法
    	decorator_operation(self);
    }
    
    int main() {
    	// 创建被装饰者
    	ConcreteComponent component = { {concrete_operation} };
    
    	// 创建具体的装饰者A
    	ConcreteDecoratorA a = {
    								{
    									{ decorator_a_operation },
    									(Component *)&component
    								}
    							};
    
    	// 创建具体的装饰者B
    	ConcreteDecoratorB b = {
    								{
    									{ decorator_b_operation },
    									(Component *)&component
    								}
    							};
    
    	// 调用装饰者A的功能
    	Component *componenta = (Component *)&a;
    	componenta->operation(componenta);
    
    	// 调用装饰者B的功能
    	Component *componentb = (Component *)&b;
    	componentb->operation(componentb);
    
    	return 0;
    }
    

外观模式- 通过封装相应操作,简化客户端操作

  • 概念: 为子系统中的一组接口提供一个一致的界面。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用

  • 规则: 其核心是将复杂接口包装起来,对外提供一个实现具体功能的接口。即通过需求出发,创建相应的外观类

  • 实现细节: 根据所客户端常见的需求,对背后的复杂系统进行封装,从而实现应用程序的调用;实现的时候需要适当选择,避免其成为上帝对象(和所有类都耦合)

  • 应用场景:需要一个指向复杂子系统的直接接口(常用功能的快捷方式);将子系统组织为多层结构。操作系统的各种操作(syscall)可以理解为外观模式的应用。

  • 示意图:
    image

  • 代码实现:

    c++
    /**
     * The Subsystem can accept requests either from the facade or client directly.
     * In any case, to the Subsystem, the Facade is yet another client, and it's not
     * a part of the Subsystem.
     */
    class Subsystem1 {
     public:
      std::string Operation1() const {
    	return "Subsystem1: Ready!\n";
      }
      // ...
      std::string OperationN() const {
    	return "Subsystem1: Go!\n";
      }
    };
    /**
     * Some facades can work with multiple subsystems at the same time.
     */
    class Subsystem2 {
     public:
      std::string Operation1() const {
    	return "Subsystem2: Get ready!\n";
      }
      // ...
      std::string OperationZ() const {
    	return "Subsystem2: Fire!\n";
      }
    };
    
    /**
     * The Facade class provides a simple interface to the complex logic of one or
     * several subsystems. The Facade delegates the client requests to the
     * appropriate objects within the subsystem. The Facade is also responsible for
     * managing their lifecycle. All of this shields the client from the undesired
     * complexity of the subsystem.
     */
    class Facade {
     protected:
      Subsystem1 *subsystem1_;
      Subsystem2 *subsystem2_;
      /**
       * Depending on your application's needs, you can provide the Facade with
       * existing subsystem objects or force the Facade to create them on its own.
       */
     public:
      /**
       * In this case we will delegate the memory ownership to Facade Class
       */
      Facade(
    	  Subsystem1 *subsystem1 = nullptr,
    	  Subsystem2 *subsystem2 = nullptr) {
    	this->subsystem1_ = subsystem1 ?: new Subsystem1;
    	this->subsystem2_ = subsystem2 ?: new Subsystem2;
      }
      ~Facade() {
    	delete subsystem1_;
    	delete subsystem2_;
      }
      /**
       * The Facade's methods are convenient shortcuts to the sophisticated
       * functionality of the subsystems. However, clients get only to a fraction of
       * a subsystem's capabilities.
       */
      std::string Operation() {
    	std::string result = "Facade initializes subsystems:\n";
    	result += this->subsystem1_->Operation1();
    	result += this->subsystem2_->Operation1();
    	result += "Facade orders subsystems to perform the action:\n";
    	result += this->subsystem1_->OperationN();
    	result += this->subsystem2_->OperationZ();
    	return result;
      }
    };
    
    /**
     * The client code works with complex subsystems through a simple interface
     * provided by the Facade. When a facade manages the lifecycle of the subsystem,
     * the client might not even know about the existence of the subsystem. This
     * approach lets you keep the complexity under control.
     */
    void ClientCode(Facade *facade) {
      // ...
      std::cout << facade->Operation();
      // ...
    }
    /**
     * The client code may have some of the subsystem's objects already created. In
     * this case, it might be worthwhile to initialize the Facade with these objects
     * instead of letting the Facade create new instances.
     */
    
    int main() {
      Subsystem1 *subsystem1 = new Subsystem1;
      Subsystem2 *subsystem2 = new Subsystem2;
      Facade *facade = new Facade(subsystem1, subsystem2);
      ClientCode(facade);
    
      delete facade;
    
      return 0;
    }
    
    c
    #include <stdio.h>
    
    // 定义子系统A
    typedef struct subsystemA {
    	void (*operationA)(struct subsystemA* subsystem);
    } SubsystemA;
    
    // 定义子系统B
    typedef struct subsystemB {
    	void (*operationB)(struct subsystemB* subsystem);
    } SubsystemB;
    
    // 定义子系统C
    typedef struct subsystemC {
    	void (*operationC)(struct subsystemC* subsystem);
    } SubsystemC;
    
    // 定义外观
    typedef struct facade {
    	SubsystemA subsystemA;
    	SubsystemB subsystemB;
    	SubsystemC subsystemC;
    	void (*operation)(struct facade* facade);
    } Facade;
    
    // 实现子系统A的操作
    void operationA(SubsystemA* subsystem) {
    	printf("SubsystemA operation.\n");
    }
    
    // 实现子系统B的操作
    void operationB(SubsystemB* subsystem) {
    	printf("SubsystemB operation.\n");
    }
    
    // 实现子系统C的操作
    void operationC(SubsystemC* subsystem) {
    	printf("SubsystemC operation.\n");
    }
    
    // 实现外观的操作
    void operation(Facade* facade) {
    	facade->subsystemA.operationA(&facade->subsystemA);
    	facade->subsystemB.operationB(&facade->subsystemB);
    	facade->subsystemC.operationC(&facade->subsystemC);
    }
    
    int main() {
    	Facade facade;
    
    	facade.subsystemA.operationA = operationA;
    	facade.subsystemB.operationB = operationB;
    	facade.subsystemC.operationC = operationC;
    	facade.operation = operation;
    
    	facade.operation(&facade);
    
    	return 0;
    }
    

    享元模式 - 通过抽取共享元素,减少空间占用

    • 前提 - 工厂模式: 享元模式可以使用工厂模式对享元的创建和使用进行优化

    • 概念: 运用共享技术有效地支持大量细粒度的对象。

    • 规则: 其本质是一种优化,针对于大量对象中共享且不变的单元,对其进行共享,从而实现代码的优化

    • 实现细节: 使用工厂模式,创建享元基类,之后情景类(外在状态)调用享元工厂模式,根据情景创建/调用享元,并为客户端提供服务。
      改写方法:将修改成员分类(固定状态—可变状态)-> 将固定状态设定为常量,并使用调用参数对固定状态进行引用 -> 创建享元缓存池

    • 应用场景: 程序需要支持大量对象,且内存有限。像COW技巧,但是没有W这一步;

    • 示意图:
      image

    • 代码实现:

    c++
    /**
     * Flyweight Design Pattern
     *
     * Intent: Lets you fit more objects into the available amount of RAM by sharing
     * common parts of state between multiple objects, instead of keeping all of the
     * data in each object.
     */
    
    struct SharedState
    {
    	std::string brand_;
    	std::string model_;
    	std::string color_;
    
    	SharedState(const std::string &brand, const std::string &model, const std::string &color)
    		: brand_(brand), model_(model), color_(color)
    	{
    	}
    
    	friend std::ostream &operator<<(std::ostream &os, const SharedState &ss)
    	{
    		return os << "[ " << ss.brand_ << " , " << ss.model_ << " , " << ss.color_ << " ]";
    	}
    };
    
    struct UniqueState
    {
    	std::string owner_;
    	std::string plates_;
    
    	UniqueState(const std::string &owner, const std::string &plates)
    		: owner_(owner), plates_(plates)
    	{
    	}
    
    	friend std::ostream &operator<<(std::ostream &os, const UniqueState &us)
    	{
    		return os << "[ " << us.owner_ << " , " << us.plates_ << " ]";
    	}
    };
    
    /**
     * The Flyweight stores a common portion of the state (also called intrinsic
     * state) that belongs to multiple real business entities. The Flyweight accepts
     * the rest of the state (extrinsic state, unique for each entity) via its
     * method parameters.
     */
    class Flyweight
    {
    private:
    	SharedState *shared_state_;
    
    public:
    	Flyweight(const SharedState *shared_state) : shared_state_(new SharedState(*shared_state))
    	{
    	}
    	Flyweight(const Flyweight &other) : shared_state_(new SharedState(*other.shared_state_))
    	{
    	}
    	~Flyweight()
    	{
    		delete shared_state_;
    	}
    	SharedState *shared_state() const
    	{
    		return shared_state_;
    	}
    	void Operation(const UniqueState &unique_state) const
    	{
    		std::cout << "Flyweight: Displaying shared (" << *shared_state_ << ") and unique (" << unique_state << ") state.\n";
    	}
    };
    /**
     * The Flyweight Factory creates and manages the Flyweight objects. It ensures
     * that flyweights are shared correctly. When the client requests a flyweight,
     * the factory either returns an existing instance or creates a new one, if it
     * doesn't exist yet.
     */
    class FlyweightFactory
    {
    	/**
    	 * @var Flyweight[]
    	 */
    private:
    	std::unordered_map<std::string, Flyweight> flyweights_;
    	/**
    	 * Returns a Flyweight's string hash for a given state.
    	 */
    	std::string GetKey(const SharedState &ss) const
    	{
    		return ss.brand_ + "_" + ss.model_ + "_" + ss.color_;
    	}
    
    public:
    	FlyweightFactory(std::initializer_list<SharedState> share_states)
    	{
    		for (const SharedState &ss : share_states)
    		{
    			this->flyweights_.insert(std::make_pair<std::string, Flyweight>(this->GetKey(ss), Flyweight(&ss)));
    		}
    	}
    
    	/**
    	 * Returns an existing Flyweight with a given state or creates a new one.
    	 */
    	Flyweight GetFlyweight(const SharedState &shared_state)
    	{
    		std::string key = this->GetKey(shared_state);
    		if (this->flyweights_.find(key) == this->flyweights_.end())
    		{
    			std::cout << "FlyweightFactory: Can't find a flyweight, creating new one.\n";
    			this->flyweights_.insert(std::make_pair(key, Flyweight(&shared_state)));
    		}
    		else
    		{
    			std::cout << "FlyweightFactory: Reusing existing flyweight.\n";
    		}
    		return this->flyweights_.at(key);
    	}
    	void ListFlyweights() const
    	{
    		size_t count = this->flyweights_.size();
    		std::cout << "\nFlyweightFactory: I have " << count << " flyweights:\n";
    		for (std::pair<std::string, Flyweight> pair : this->flyweights_)
    		{
    			std::cout << pair.first << "\n";
    		}
    	}
    };
    
    // ...
    void AddCarToPoliceDatabase(
    	FlyweightFactory &ff, const std::string &plates, const std::string &owner,
    	const std::string &brand, const std::string &model, const std::string &color)
    {
    	std::cout << "\nClient: Adding a car to database.\n";
    	const Flyweight &flyweight = ff.GetFlyweight({brand, model, color});
    	// The client code either stores or calculates extrinsic state and passes it
    	// to the flyweight's methods.
    	flyweight.Operation({owner, plates});
    }
    
    /**
     * The client code usually creates a bunch of pre-populated flyweights in the
     * initialization stage of the application.
     */
    
    int main()
    {
    	FlyweightFactory *factory = new FlyweightFactory({{"Chevrolet", "Camaro2018", "pink"}, {"Mercedes Benz", "C300", "black"}, {"Mercedes Benz", "C500", "red"}, {"BMW", "M5", "red"}, {"BMW", "X6", "white"}});
    	factory->ListFlyweights();
    
    	AddCarToPoliceDatabase(*factory,
    							"CL234IR",
    							"James Doe",
    							"BMW",
    							"M5",
    							"red");
    
    	AddCarToPoliceDatabase(*factory,
    							"CL234IR",
    							"James Doe",
    							"BMW",
    							"X1",
    							"red");
    	factory->ListFlyweights();
    	delete factory;
    
    	return 0;
    }
    
    c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    // 享元接口
    typedef struct {
    	void (*operation)(void* data);
    } Flyweight;
    
    // 具体享元实现
    typedef struct {
    	Flyweight base;
    	char name[50];
    } ConcreteFlyweight;
    
    void ConcreteFlyweight_operation(void* data) {
    	ConcreteFlyweight* flyweight = (ConcreteFlyweight*)data;
    	printf("ConcreteFlyweight Operation: %s\n", flyweight->name);
    }
    
    // 享元工厂
    typedef struct {
    	int capacity;
    	int count;
    	Flyweight** flyweights;
    } FlyweightFactory;
    
    FlyweightFactory* FlyweightFactory_create(int capacity) {
    	FlyweightFactory* factory = (FlyweightFactory*)malloc(sizeof(FlyweightFactory));
    	factory->capacity = capacity;
    	factory->count = 0;
    	factory->flyweights = (Flyweight**)malloc(capacity * sizeof(Flyweight*));
    	return factory;
    }
    
    Flyweight* FlyweightFactory_getFlyweight(FlyweightFactory* factory, const char* name) {
    	for (int i = 0; i < factory->count; i++) {
    		ConcreteFlyweight* flyweight = (ConcreteFlyweight*)factory->flyweights[i];
    		if (strcmp(flyweight->name, name) == 0) {
    			return &flyweight->base;
    		}
    	}
    
    	if (factory->count >= factory->capacity) {
    		printf("FlyweightFactory is full\n");
    		return NULL;
    	}
    
    	ConcreteFlyweight* flyweight = (ConcreteFlyweight*)malloc(sizeof(ConcreteFlyweight));
    	flyweight->base.operation = ConcreteFlyweight_operation;
    	strcpy(flyweight->name, name);
    	factory->flyweights[factory->count] = (Flyweight*)flyweight;
    	factory->count++;
    	return &flyweight->base;
    }
    
    void FlyweightFactory_destroy(FlyweightFactory* factory) {
    	for (int i = 0; i < factory->count; i++) {
    		free(factory->flyweights[i]);
    	}
    	free(factory->flyweights);
    	free(factory);
    }
    
    // 客户端模块
    int main() {
    	FlyweightFactory* factory = FlyweightFactory_create(5);
    
    	// 获取享元对象并执行操作
    	Flyweight* flyweight1 = FlyweightFactory_getFlyweight(factory, "Object1");
    	if (flyweight1 != NULL) {
    		flyweight1->operation(flyweight1);
    	}
    
    	Flyweight* flyweight2 = FlyweightFactory_getFlyweight(factory, "Object2");
    	if (flyweight2 != NULL) {
    		flyweight2->operation(flyweight2);
    	}
    
    	Flyweight* flyweight3 = FlyweightFactory_getFlyweight(factory, "Object1"); // 已存在的对象,直接返回
    	if (flyweight3 != NULL) {
    		flyweight3->operation(flyweight3);
    	}
    
    	FlyweightFactory_destroy(factory);
    
    	return 0;
    }
    

代理模式 -不基于对象的方法的封装

  • 概念: 为其他对象提供一种代理以控制对这个对象的访问。

  • 规则: 其本质是在客户端和服务端之间插入一层代理,实现对服务端提供服务的优化,如实现延迟写等

  • 实现细节: 接口的创建可以通过继承服务类/抽取接口创建接口->创建代理类,其中需要包含一个存储指向服务类的引用的成员变量。同时,代理方法的实现是面向特定需求的,完成任务后应该将后续任务委派给服务类。在操作系统中,文件系统中的日志系统就是对底层硬盘读写的代理。

  • 应用场景: 延迟初始化(虚拟代理),即COW;访问控制(保护代理),即权限控制;本地执行远程服务(远程代理),类似于SSH;记录日志请求(日志记录代理),文件系统和数据库的日志系统;缓存请求结果(缓存代理),即快表;智能引用,文件系统/缓存池。

  • 示意图:
    image

  • 注: 装饰模式是基于客户端的,其生命周期和客户端一致,而代理模式是基于独立的,其自行管理声明周期。

  • 代码实现:

    c++
    #include <iostream>
    /**
     * The Subject interface declares common operations for both RealSubject and the
     * Proxy. As long as the client works with RealSubject using this interface,
     * you'll be able to pass it a proxy instead of a real subject.
     */
    class Subject {
     public:
      virtual void Request() const = 0;
    };
    /**
     * The RealSubject contains some core business logic. Usually, RealSubjects are
     * capable of doing some useful work which may also be very slow or sensitive -
     * e.g. correcting input data. A Proxy can solve these issues without any
     * changes to the RealSubject's code.
     */
    class RealSubject : public Subject {
     public:
      void Request() const override {
    	std::cout << "RealSubject: Handling request.\n";
      }
    };
    /**
     * The Proxy has an interface identical to the RealSubject.
     */
    class Proxy : public Subject {
      /**
       * @var RealSubject
       */
     private:
      RealSubject *real_subject_;
    
      bool CheckAccess() const {
    	// Some real checks should go here.
    	std::cout << "Proxy: Checking access prior to firing a real request.\n";
    	return true;
      }
      void LogAccess() const {
    	std::cout << "Proxy: Logging the time of request.\n";
      }
    
      /**
       * The Proxy maintains a reference to an object of the RealSubject class. It
       * can be either lazy-loaded or passed to the Proxy by the client.
       */
     public:
      Proxy(RealSubject *real_subject) : real_subject_(new RealSubject(*real_subject)) {
      }
    
      ~Proxy() {
    	delete real_subject_;
      }
      /**
       * The most common applications of the Proxy pattern are lazy loading,
       * caching, controlling the access, logging, etc. A Proxy can perform one of
       * these things and then, depending on the result, pass the execution to the
       * same method in a linked RealSubject object.
       */
      void Request() const override {
    	if (this->CheckAccess()) {
    	  this->real_subject_->Request();
    	  this->LogAccess();
    	}
      }
    };
    /**
     * The client code is supposed to work with all objects (both subjects and
     * proxies) via the Subject interface in order to support both real subjects and
     * proxies. In real life, however, clients mostly work with their real subjects
     * directly. In this case, to implement the pattern more easily, you can extend
     * your proxy from the real subject's class.
     */
    void ClientCode(const Subject &subject) {
      // ...
      subject.Request();
      // ...
    }
    
    int main() {
      std::cout << "Client: Executing the client code with a real subject:\n";
      RealSubject *real_subject = new RealSubject;
      ClientCode(*real_subject);
      std::cout << "\n";
      std::cout << "Client: Executing the same client code with a proxy:\n";
      Proxy *proxy = new Proxy(real_subject);
      ClientCode(*proxy);
    
      delete real_subject;
      delete proxy;
      return 0;
    }
    
    c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    //定义一个接口
    typedef struct {
    	void (*doOperation)(void *object);
    } IRealObject;
    
    //创建真实对象结构体
    typedef struct {
    	IRealObject interface;
    } RealObject;
    
    //创建代理对象结构体
    typedef struct {
    	IRealObject interface;
    	RealObject real_object;
    } Proxy;
    
    //实现真实对象的操作方法
    void real_operation(void *object)
    {
    	printf("Performing operation in RealObject\n");
    }
    
    //实现代理对象的操作方法
    void proxy_operation(void *object)
    {
    	Proxy *proxy = (Proxy *)object;
    
    	if (proxy == NULL) {
    		printf("proxy is NULL in proxy_operation\n");
    	return;
    	}
    
    	printf("Performing operation in ProxyObject\n");
    
    	if (proxy->real_object.interface.doOperation == NULL) {
    		proxy->real_object.interface.doOperation = real_operation;
    	}
    
    	proxy->real_object.interface.doOperation(&proxy->real_object);
    }
    
    //创建proxy初始化函数
    IRealObject *create_proxy(void)
    {
    	Proxy *proxy = calloc(1, sizeof(Proxy));
    	if (proxy == NULL) {
    		printf("proxy is creat in create_proxy\n");
    		return 0;
    	}
    
    	if (proxy->interface.doOperation == NULL)
    		proxy->interface.doOperation = proxy_operation;
    
    	return &proxy->interface;
    }
    
    //销毁proxy
    void destory_proxy(void *object)
    {
    	Proxy *proxy = (Proxy *)object;
    
    	if (proxy) {
    		free(proxy);
    	}
    }
    
    //客户端代码
    int main()
    {
    	IRealObject *interface = NULL;
    
    	interface = create_proxy();
    
    	//调用代理对象的操作方法
       interface->doOperation(interface);
    
       destory_proxy(interface);
    
    	return 0;
    }
    

参考文献

廖雪峰的官方网站: https://www.liaoxuefeng.com/wiki/1252599548343744/1264742167474528
c语言和设计模式:https://blog.csdn.net/feixiaoxing/category_951264.html
卡码网设计模式精讲:https://github.com/youngyangyang04/kama-DesignPattern
设计模式:https://www.zhihu.com/column/c_1605852722795917312
设计模式:https://www.zhihu.com/people/infinity-65-77/posts
深入设计模式:https://refactoringguru.cn/design-patterns/builder/cpp/example

标签:std,struct,23,composite,void,Component,operation,设计模式,结构型
From: https://www.cnblogs.com/David-Dong/p/18165113

相关文章

  • ISCC线上赛2023
    ISCC线上赛2023webweb1双重base解码得到flagweb3F12控制台查看可找到loveStory.phpEnc.phpdownload.php,loveStory.php为反序列源码boy::__destruct()-->girl()::__call()-->helper()::__isset()-->boy()::__toString()-->helper()::__get()-->love_story()::__love()......
  • 程设2023期末
    A.围栏#include<iostream>usingnamespacestd;intmain(){ longlongn,ans=0;cin>>n; for(longlongi=1;i<=n;++i){ longlongtmp=(n+i-1)/i; if(tmp<i)break; ans=max(ans,(i+tmp)*2); }cout<<ans<&l......
  • [COCI2022-2023#1] Berilij 题解
    SolutionP9030[COCI2022-2023#1]Berilij本题解转载翻译自官方题解:COCI2022/2023CONTEST1Part1让我们定义图形\(G\),顶点代表飞船,边代表两艘飞船外部接触的情况。此外,让边的边权成为它所连接的圆之间的距离。现在的任务等同于为顶点找到非负值,使得每条边所连接的两个顶......
  • 2024.4.23
    继续之前任务@keyframescuIcon-spin{ 0%{ -webkit-transform:rotate(0); transform:rotate(0); } 100%{ -webkit-transform:rotate(359deg); transform:rotate(359deg); }}.cuIconfont-spin{ -webkit-animation:cuIcon-spin2sinfinitelinear; animation:cuIc......
  • 界面控件DevExtreme v23.1、v23.2盘点 - 增强的TypeScript(Angular、React、Vue)
    DevExtreme拥有高性能的HTML5/JavaScript小部件集合,使您可以利用现代Web开发堆栈(包括React,Angular,ASP.NETCore,jQuery,Knockout等)构建交互式的Web应用程序。从Angular和Reac,到ASP.NETCore或Vue,DevExtreme包含全面的高性能和响应式UI小部件集合,可在传统Web和下一代移动应用程序中......
  • 232自由口转Profinet网关接AB扫码枪与PLC通讯案例
     232自由口转Profinet网关(XD-PNR100/300),是一种用于将自由协议转换为Profinet协议的设备,可以实现不同网络之间的通信和数据交换。232自由口转Profinet网关高度的灵活性和可靠性使其成为工业自动化领域的重要工具,并将其与Profinet网络无缝集成,实现数据的快速传输和交换。另外23......
  • 【设计模式】策略模式
    一、介绍策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够相互替换。这里列举两个例子来说明下策略模式的使用场景:(1)根据会员等级来计算折扣力度。不同等级拥有不同的折扣力度,这样就可以根据策略模式去灵活的计算,就算之后又......
  • 设计模式笔记
    简单记一下方便需要的时候看设计模式原则总原则:开闭原则--对扩展开放,对修改关闭单一职责里氏替换--任何基类可以出现的地方,子类一定可以出现依赖倒置--依赖于抽象而不依赖于具体接口隔离--类间的依赖关系应该建立在最小的接口上最少知道--只和朋友交谈首......
  • hdu 1232通畅工程
    与hdu1213一样简单并查集。点击查看代码importjava.util.Scanner;publicclasshdu1232{ publicstaticvoidmain(String[]args){ //TODO自动生成的方法存根 Scannersc=newScanner(System.in); while(sc.hasNext()){ intn=sc.nextInt(); if(n......
  • 腾讯公益赛冲刺个人博客1(2024.4.23)
    今天确定了组内第一阶段的任务是基本完成sos和帮扶两个核心功能以及登录注册等常规功能完成登录和注册的基本页面以及数据库的设计packagecom.example.helppeople.entity;publicclassStudent{privateStringid;privateStringname;privateStringphon......