内容目录
工厂模式和抽象工厂模式,都是避免调用者直接 new 一个新的实例,预先将创建逻辑编写在工厂代码中,并且对实例进行和一些配置,然后分配调用者使用。
原有代码:
HttpRequest 作用是检查网址是否能够访问以及健康状态。
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace Children
{
class Program
{
static void Main(string[] args)
{
HttpRequest request = new HttpRequest("https://whuanle.cn");
HttpStatusCode code = request.GetAsync().Result;
Console.WriteLine("网站状态:" + Enum.GetName(code.GetType(), code));
Console.ReadKey();
}
}
///
/// 代码加工厂
///
public class HttpRequest
{
private HttpClient httpClient;
private Uri uri;
public HttpRequest(string url)
{
uri = new Uri(url);
httpClient = new HttpClient();
}
public async Task GetAsync()
{
var request = await httpClient.GetAsync(uri);
return request.StatusCode;
}
}
}
这里出来新的问题:
- 使用者调用时,要自己传递 URL,容易出错
- 限定只能访问约定的几个网站,不能自己随便填写 URL 地址
- ... ...
首先使用工厂方法来优化:
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace Children
{
class Program
{
static void Main(string[] args)
{
IRequest request = Factory.Create(UrlType.Baidu);
HttpStatusCode code = request.GetAsync().Result;
Console.WriteLine("网站状态:" + Enum.GetName(code.GetType(), code));
Console.ReadKey();
}
}
#region
public interface IRequest
{
Task GetAsync();
}
public class BaiduRequest : IRequest
{
private HttpClient httpClient = new HttpClient();
private Uri uri = new Uri("https://www.baidu.com");
public async Task GetAsync()
{
var request = await httpClient.GetAsync(uri);
return request.StatusCode;
}
}
public class QQRequest : IRequest
{
private HttpClient httpClient = new HttpClient();
private Uri uri = new Uri("https://www.qq.com");
public async Task GetAsync()
{
var request = await httpClient.GetAsync(uri);
return request.StatusCode;
}
}
#endregion
#region
public enum UrlType
{
Baidu = 1,
QQ = 2
}
public static class Factory
{
public static IRequest Create(UrlType type)
{
switch (type)
{
case UrlType.Baidu:
return new BaiduRequest();
case UrlType.QQ:
return new QQRequest();
}
return default;
}
}
#endregion
}
但是又出现了新的问题,就是一个网站有多个页面,要判断多个页面的情况。
假设两个网站,都只有两个页面,One,Two;
使用抽象工厂模式如下:
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace Children
{
class Program
{
static void Main(string[] args)
{
ICreateFactory factory = FactoryFactory.Create(UrlType.BAIDU);
IRequest request = factory.One();
HttpStatusCode code = request.GetAsync().Result;
Console.WriteLine("网站状态:" + Enum.GetName(code.GetType(), code));
Console.ReadKey();
}
}
#region 共同继承
// 创建工厂模式的接口,给抽象工厂模式使用的
public interface ICreateFactory
{
IRequest One();
IRequest Two();
}
// 访问页面
public interface IRequest
{
Task GetAsync();
}
#endregion
#region 访问百度百科相应页面
public abstract class IBaiduRequest : IRequest
{
protected HttpClient httpClient = new HttpClient();
protected Uri baseUri = new Uri("https://baike.baidu.com/");
public abstract Task GetAsync();
}
public class Baidu_DOTNET_Request : IBaiduRequest
{
protected Uri thisUri;
public Baidu_DOTNET_Request()
{
Uri.TryCreate(baseUri, "item/.NET", out thisUri);
}
public override async Task GetAsync()
{
var request = await base.httpClient.GetAsync(thisUri);
return request.StatusCode;
}
}
public class Baidu_Microsoft_Request : IBaiduRequest
{
protected Uri thisUri;
public Baidu_Microsoft_Request()
{
Uri.TryCreate(baseUri, "item/Microsoft", out thisUri);
}
public override async Task GetAsync()
{
var request = await base.httpClient.GetAsync(thisUri);
return request.StatusCode;
}
}
#endregion
#region 访问 QQ
public abstract class IQQRequest : IRequest
{
protected HttpClient httpClient = new HttpClient();
protected Uri baseUri = new Uri("https://new.qq.com/");
public abstract Task GetAsync();
}
public class QQ_Images_Request : IQQRequest
{
protected Uri thisUri;
public QQ_Images_Request()
{
Uri.TryCreate(baseUri, "ch/photo", out thisUri);
}
public override async Task GetAsync()
{
var request = await base.httpClient.GetAsync(thisUri);
return request.StatusCode;
}
}
public class QQ_OMN_Request : IQQRequest
{
protected Uri thisUri;
public QQ_OMN_Request()
{
Uri.TryCreate(baseUri, "omn/author/5114481", out thisUri);
}
public override async Task GetAsync()
{
var request = await base.httpClient.GetAsync(thisUri);
return request.StatusCode;
}
}
#endregion
#region 工厂模式和抽象工厂模式
// 访问百度的工厂模式
public class CreateBaidu : ICreateFactory
{
public IRequest One()
{
return new Baidu_DOTNET_Request();
}
public IRequest Two()
{
return new Baidu_Microsoft_Request();
}
}
// 访问QQ的工厂模式
public class CreateQQ : ICreateFactory
{
public IRequest One()
{
return new QQ_Images_Request();
}
public IRequest Two()
{
return new QQ_OMN_Request();
}
}
public enum UrlType
{
BAIDU = 1,
QQ = 2
}
// 抽象工厂模式
public static class FactoryFactory
{
public static ICreateFactory Create(UrlType type)
{
switch (type)
{
case UrlType.BAIDU:
return new CreateBaidu();
case UrlType.QQ:
return new CreateQQ();
}
return default;
}
}
#endregion
}
工厂模式和抽象工厂模式的变体很多。
工厂模式是一层,可以通过工厂类创建类型;
抽象工厂模式是通过工厂模式创建一个工厂(一层),这个工厂继续创建新的工厂(二层),然后再创建类型。
文章评论