设计模式1:C#开发中使用创建型的工厂模式和行为型的策略模式

server/2024/10/9 11:28:19/

一、接口设计的好处

三大好处:解耦、可复用、可扩展。

二、简单工厂模式

【三要素】能创建具体产品的工厂、抽象产品(接口)、具体产品

【基本用法】字符串=>创建对象=>调用其方法

// 产品接口
public interface IProduct
{void Operation();
}// 具体产品 A
public class ProductA : IProduct
{public void Operation() => Console.WriteLine("ProductA Operation");//表达式主体方法写法,就是写括号
}// 具体产品 B
public class ProductB : IProduct
{public void Operation() => Console.WriteLine("ProductB Operation");
}// 工厂类
public class ProductFactory
{public static IProduct CreateProduct(string type){return type switch //简化版switch 语句,和if,else一个意思{"A" => new ProductA(),"B" => new ProductB(),_ => throw new ArgumentException("Invalid product type")};}
}// 主程序
class Program
{static void Main(){string input = "A";IProduct product = ProductFactory.CreateProduct(input);product.Operation(); // Output: ProductA Operation}
}

【思考】以下方法也可以调用接口,为什么非要用工厂模式呢?

string input = "A";
if (input=="A")
{var product = new ProductA();product.Operation();
}

        请看图,我告诉你为什么要用工厂模式:

1.假如后续我加了产品CDEFGHI...,我仅需要添加代码到工厂类和具体实现 (底层代码),而无需修改高层代码,做到了开闭原则

2.用工厂模式实现了解耦,避免了高层代码和底层代码紧密的联系,使得高层代码无需关注具体的实现过程,做到了依赖于抽象,不依赖于具体(依赖倒置原则)。

三、抽象工厂模式

【思考】简单工厂和抽象工厂的区别

简单工厂模式:适用于单一类型的对象创建。
抽象工厂模式:适合创建一系列相关的产品族,每个产品族包含多个不同类型的产品。它提供了更高的灵活性和扩展性。

【代码实现】 

// 抽象产品 A
public interface IProductA
{void OperationA();
}// 抽象产品 B
public interface IProductB
{void OperationB();
}// 具体产品 A1
public class ProductA1 : IProductA
{public void OperationA() => Console.WriteLine("ProductA1 OperationA");
}// 具体产品 B1
public class ProductB1 : IProductB
{public void OperationB() => Console.WriteLine("ProductB1 OperationB");
}// 具体产品 A2
public class ProductA2 : IProductA
{public void OperationA() => Console.WriteLine("ProductA2 OperationA");
}// 具体产品 B2
public class ProductB2 : IProductB
{public void OperationB() => Console.WriteLine("ProductB2 OperationB");
}// 抽象工厂
public interface IFactory
{IProductA CreateProductA();IProductB CreateProductB();
}// 具体工厂 1
public class Factory1 : IFactory
{public IProductA CreateProductA() => new ProductA1();public IProductB CreateProductB() => new ProductB1();
}// 具体工厂 2
public class Factory2 : IFactory
{public IProductA CreateProductA() => new ProductA2();public IProductB CreateProductB() => new ProductB2();
}// 主程序
class Program
{static void Main(){IFactory factory = new Factory1();IProductA productA = factory.CreateProductA();IProductB productB = factory.CreateProductB();productA.OperationA(); // Output: ProductA1 OperationAproductB.OperationB(); // Output: ProductB1 OperationB}
}

四、策略模式

【三要素】环境类(用户这个对象)、策略接口、实现接口

【基本用法】对象不同=>选择的策略不同=>实现策略不同 

【demo】

using System;public interface IDiscountStrategy
{double ApplyDiscount(double price);
}public class GoldMemberDiscount : IDiscountStrategy
{public double ApplyDiscount(double price){return price * 0.95; // 5% off}
}public class RegularMemberDiscount : IDiscountStrategy
{public double ApplyDiscount(double price){return price; // No discount}
}public class Ticket
{private readonly IDiscountStrategy _discountStrategy;public Ticket(IDiscountStrategy discountStrategy){_discountStrategy = discountStrategy;}public double GetPrice(double originalPrice){return _discountStrategy.ApplyDiscount(originalPrice);}
}public class Program
{public static void Main(){double originalPrice = 100.0;//策略模式:分为两步Ticket goldMemberTicket = new Ticket(new GoldMemberDiscount());//1.选择策略Console.WriteLine("Gold Member Price: " + goldMemberTicket.GetPrice(originalPrice));//2.执行策略Ticket regularMemberTicket = new Ticket(new RegularMemberDiscount());Console.WriteLine("Regular Member Price: " + regularMemberTicket.GetPrice(originalPrice));}
}

 【思考】为什么要选取策略模式?其实分析思路和工厂模式差不多:
1.符合开闭原则,新加策略可以直接加实现策略即可,而工厂模式还需要修改工厂类和实现产品。
2.消除if-else语句,将算法逻辑封装在了具体策略中,高层代码(主程序)只需要调用GetPrice 方法即可(用户的身份信息可由查表获得,无需if判断)。
3.复用性强,一套算法可以多次使用。


http://www.ppmy.cn/server/112462.html

相关文章

9、类和对象

9.1 封装 9.1.1 封装的例子 class Student { public:string name;int age; public:void setName(string name_) {name name_;} }; int main() {Student s1;s1.setName("zhangsan");return 0; }类中的行为都叫做成员,例如成员属性,成员变量&…

前端框架有哪些?全面解析主流前端框架

一、React React 是由 Facebook 开发和维护的一个前端框架,它专注于构建用户界面。React 采用组件化的开发模式,允许开发者将用户界面拆分成多个可复用的组件。 主要特点 组件化: React 的核心是组件,它允许开发者将界面拆分成独立的、可复…

Aninworth算法

绪论 偏置极化信息,就是对极化数据做出了假设,再进行校准,得到的极化信息就更像假设的极化,失去了原有的一些极化信息 模型 从上面直接得到的模型可看出,当散射矩阵乘以发发射或解说矩阵时,交叉极化hv vh…

软件测试 - 性能测试 (概念)(并发数、吞吐量、响应时间、TPS、QPS、基准测试、并发测试、负载测试、压力测试、稳定性测试)

一、性能测试 目标:能够对个人编写的项目进行接口的性能测试。 一般是功能测试完成之后,最后做性能测试。性能测试是一个很大的范围,在学习过程中很难直观感受到性能。 以购物软件为例: 1)购物过程中⻚⾯突然⽆法打开…

【Go 快速入门】Go Test 工具 | 单元测试 | 基准测试

文章目录 go test工具单元测试子测试测试覆盖率 基准测试性能比较函数重置时间并行测试 本节项目地址:07-UnitTestBenchmarkTest go test工具 Go语言中的测试依赖go test,该命令是一个按照一定约定和组织的测试代码的驱动程序。在包目录内,…

Linux字符设备驱动 -- regulator子系统

文章目录 环境regulator子系统简介:Regulator设备的注册Consumer设备的注册 环境 linux 4.9 armv8-A regulator子系统简介: 关于regulator子系统,可以看下这这些博客: Linux驱动之Regulator子系统Linux 内核之电源篇(加载流程…

关于Java中Comparable和Comparator用于排序中的理解,以Comparable为例

在Java中,当一个对象实现了 Comparable 接口,这意味着该对象的类定义了一个自然的排序标准。Comparable 接口要求实现它的类必须实现 compareTo 方法,这个方法定义了对象之间的比较规则。 目录 一、为什么使用 compareTo 方法: 二…

Linux: 手动编译安装指定内核的perf工具

文章目录 1. 引言2. 安装开发工具和依赖3. 下载内核源代码4. 编译 perf 工具5. 验证 perf 工具的安装6. 解决编译中的依赖问题(选看)6.1 安装缺少的依赖项6.2 手动编译 libtraceevent 库安装libtraceevent编译工具和依赖克隆 libtraceevent 源代码编译和…