您的位置:首页 > 编程语言 > C#

C#设计模式中细节总结-持续更新中

2012-12-16 14:17 543 查看

C#设计模式细节问题总结-持续更新

在这里不光是程序中的细节问题,更多的是学习设计模式

1、工厂模式

1.1简单工厂模式

学习工厂模式,首先学习的肯定是简单工厂模式,它虽然不属于GoF23中设计模式,但是应用较为频繁,同时它也是学习其他创建型模式的基础

简单工厂中包含这样三个角色:工厂-具体产品-抽象产品(这里的抽象产品是为了实现抽象编程而定义的)

对简单工厂模式通俗易懂的理解:我(实现)想吃苹果(具体产品),我会去超市(工厂)买,而不是自己去种

实例:女娲造人,分别是Man、Woman、Robot



下面再看具体代码:

抽象产品-Nvawa

using System;

public interface Nvwa
{
void Person();

}


具体产品-Robot(另两个具体产品类就不在此一一贴出.)

using System;

public class Robot : Nvwa
{

public void Person()
{
Console.WriteLine("Robot人");
}
}


工厂-Factory

using System;

public class Factory
{
public static Nvwa ProducePerson(string brand)
{
if(brand.ToString()=="man")
{
Console.WriteLine("女娲造人Man人");
return new Man();
}
else if (brand.ToString()=="robot")
{
Console.WriteLine("女娲造人Robot人");
return new Robot();
}
else if (brand.ToString() == "woman")
{
Console.WriteLine("女娲造人Woman人");
return new Woman();
}
else
{
throw new Exception("对不起,不能生产");
}
}

}


App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="brand" value="robot"/>
</appSettings>
</configuration>


Program(测试类):

using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;

namespace P743
{
class Program
{
static void Main(string[] args)
{
string brand = ConfigurationManager.AppSettings["brand"];
try
{
Nvwa nvwa;
nvwa = Factory.ProducePerson(brand);
nvwa.Person();
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
}
}


运行结果:

女娲造人Robot人

Robot人

--------------------------------------------------------------------------------------------------------

-->在配置文件App.config中更改Value值则更改造人对象.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

下面开始说编程中出现的细节问题及解决办法,首先,请读者看到工厂类.

因为是实现接口编程,所以,在工厂类应该是实现所有类的的方法,及三个类的方法,

现在提出问题:如果将这样一段语句注释,程序会报错吗?

//else
//{
//    throw new Exception("对不起,不能生产");
//}


答案是会报错:

错误 1 “Factory.ProducePerson(string)”: 并非所有的代码路径都返回值

为什么会出现这样一个错误,问题在于我们的if语句

在if 语句中 , 如果出现return关键字,并且程序中又用到多重判断,及else if语句.那么,在多重判断中,一定是以else结尾,而不是以else if语句结尾.否则,程序将报上叙错误

1.2 工厂方法模式

上面说了简单工厂模式中,只提供了一个工厂类,所以简单工厂的最大缺点是当有新产品要加入到系统中时,必须修改工厂类,这违背了"开闭原则".下面说的工厂方法模式,保持简单工厂的优点,而且克服了他的缺点.下面看UML图就一目了然.



工厂方法类的核心是一个抽象工厂类,具体工厂根据具体产品生产,这样,就很好的符合了"开闭原则",当需要添加新产品时,只需要增加相印的工厂和产品类即可,正如上图,当我需要增加一个大众汽车时,只需要增加一个生产大众汽车的具体工厂和具体产品.实现接口编程即可.

下面贴出代码:

抽象工厂类 Factory

public interface Factory
{
Car Yield();

}


具体工厂类(BMW宝马) BMWFactory

public class BMWFactory : Factory
{
public Car Yield()
{
Console.WriteLine("BMW工厂生产BMW汽车");
return new Bwm();
}

}


具体工厂类(Benz奔驰) BenzFactory

public class BenzFactory : Factory
{
public Car Yield()
{
Console.WriteLine("Benz工厂生产Benz汽车");
return new Benz();
}
}


抽象产品类 Car

public interface Car
{
void Start();

}


具体产品类 BWM

public class Bwm : Car
{
public void Start()
{
Console.WriteLine("BWM汽车启动");
}

}


具体产品类 Benz

public class Benz : Car
{
public void Start()
{
Console.WriteLine("Benz汽车启动");
}

}


App.config配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="factory" value="BMWFactory"/>
</appSettings>
</configuration>


测试类 Program

namespace P913
{
class Program
{
static void Main(string[] args)
{
Car car;
Factory factory;
string carFactory = ConfigurationManager.AppSettings["factory"];
factory = (Factory)Assembly.Load("P913").CreateInstance(carFactory);
car = factory.Yield();
car.Start();
Console.ReadLine();
}
}
}


运行结果:

BMW工厂生产BMW汽车

BWM汽车启动

--------------------------------------------------------------------------------------------------------

-->在配置文件App.config中更改Value值则更改具体工厂类.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

下面说一下工厂方法模式中用到的一种技巧:


反射


反射(Reflection)是.NET的重要机制之一,通过反射,可以在运行时获得.NET中每一个类型(包括类,结构,委托,接口,枚举等)的成员,包括方法,属性,事件,以及构造函数等,可以获得每一个成员的名称,限定符和参数等.由于获取了构造函数的信息,因此可以通过类名来直接创建对象,即使这个对象的类型在编译时是未知的.

看到测试类的这一段代码:

string carFactory = ConfigurationManager.AppSettings["factory"];
factory = (Factory)Assembly.Load("P913").CreateInstance(carFactory);

//导入命名空间

using System.Reflection;

object obj = Assembly.Load("程序集名称").CerateInstance("命名空间.类");

在第二行就是用了反射,因为抽象类是不能直接 new 的 , 而我们恰恰由要用到它,怎么办 ,这里就用到了反射,可以在不用 new 关键字的前提下 ,针对与抽象编程.

---------------------------------------------------->更新中
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: