假如说一个类依赖具体类:
1 class a
2 {
3 public void show()
4 {
5
6 }
7 }
8
9 class b
10 {
11 public void fun()
12 {
13 a s = new a();
14 // ......
15
16 s.show();
17
18 // .....
19
20 s.show();
21
22 }
23
24 }
如果需求变了,我增加了一个具体类a1,也实现show()方法,那我需要改的地方就是fun()函数中的这一处:a1 s=new a1();
假如说类b依赖于抽象类:
1 abstract class aa
2 {
3 public abstract void show();
4 }
5
6 class a
7 {
8 public override void show()
9 {
10
11 }
12 }
13
14 class b
15 {
16 public void fun()
17 {
18 aa s = new a();
19 // ......
20
21 s.show();
22
23 // .....
24
25 s.show();
26
27 }
28
29 }
如果需求变了,我需要增加一个具体类a1,继承抽象类aa,并且我也需要修改的地方是fun()函数中的这一处: aa s=new a1();
可以看到,虽然利用抽象了,但是我还得改,并且改的还都一样。
所以不太明白利用抽象封装变化点这个问题
修改是必须的,要考虑的是怎么修改的最少。
考虑这种情况:每个类写成一个单独的文件,同时有多处使用了具体类A,那么需求变化时,这些文件都要改;而用抽象类的时候,只要改创建对象的语句就行了。
例
file1
abstract class A
{
show();
}
file2
class AA:A
{
show();
}
file3
class Pro
{
A a ;
Pro(A a)
{
this.a=a;
}
DoWork()
{
a.Show();
}
}
这样呢?
class b
15 {
public aa s;
16 public void fun()
17 {
18
20
21 s.show();
22
23 // .....
24
25 s.show();
26
27 }
28
29 }
这个aa类型由外部赋值。
由外部赋值的话,外部也肯定会有创建具体类的语句呀,那样还是需要修改,只不过修改外部了
@cnin: 我汗,难道你想写一个万能程序不成?开闭原则怎么说的?
public abstract class AA
{
public abstract void Show();
}
public class A1 : AA
{
public override void Show()
{
Console.WriteLine("A1 Show");
}
}
public class A2 : AA
{
public override void Show()
{
Console.WriteLine("A2 Show");
}
}
public class B
{
private AA s = new A1(); //最好提供一个default对象
public AA A
{
get { return s; }
set { s = value; }
}
public void fun()
{
// do something
s.Show();
}
}
public class APP
{
public static void Test()
{
B b = new B();
b.fun();
b.A = new A2(); //这里可以提供一个factory对象适应创建工作
b.fun();
}
}
举个例子:
public abstract class Che
{
public void Drive()
{
// 车都可以行驶
}
// 但不都可以装货
public abstract void ZhuangHuo();
}
public class Car
{
// 小汽车不能装货
override ...
}
public class Truck
{
// 大卡车可以装货
override ...
}
个人觉得这里可以用个简单工厂
public abstract class aa
{
public abstract void Show();
}
public class a : aa
{
public override void Show()
{
throw new NotImplementedException();
}
}
public class a1 : aa
{
public override void Show()
{
throw new NotImplementedException();
}
}
///<summary>
/// 用工厂隐藏对象的创建
///</summary>
public class Factory
{
private aa model;
public Factory(int tid)
{
switch(tid)
{
case 1:
model = new a();
break;
case 2:
model = new a1();
break;
}
}
public void Show()
{
model.Show();
}
}
public class b
{
public void fun()
{
Factory instance = new Factory(1);
instance.Show();
}
}
工厂模式的意义就在于对于客户端隐藏对象的创建。客户端不需要知道 A 还是A1。
每次调整需要改的就是实例化工厂的时候传递不同的参数。
你的所有扩展例如增加A2 A3 A4 都只需要调整工厂类。
希望对你有帮助。
拙见 见笑。
可能大家没理解我的意思,我已经找到答案了:
但事实上我们需要明白,利用抽象的方式封装变化,固然是应对需求变化的王道,但它也仅仅能解除调用者与被调用者相对的耦合关系,只要还涉及到具体对象的创建,即使引入了工厂模式,但具体的工厂对象的创建仍然是必不可少的。那么,对于这样一些业已被封装变化的对象,我们还应该充分利用“依赖注入”的方式来彻底解除两者之间的耦合。(引自张逸大哥的文章)