首页新闻找找看学习计划

关于利用抽象封装变化点的问题

0
悬赏园豆:5 [已解决问题] 解决于 2011-12-15 08:27

假如说一个类依赖具体类:

View Code
 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依赖于抽象类:

View Code
 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();

 

可以看到,虽然利用抽象了,但是我还得改,并且改的还都一样。

所以不太明白利用抽象封装变化点这个问题



 

cnin的主页 cnin | 初学一级 | 园豆:172
提问于:2011-12-14 11:37
< >
分享
最佳答案
0

修改是必须的,要考虑的是怎么修改的最少。

考虑这种情况:每个类写成一个单独的文件,同时有多处使用了具体类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();

 }

}

 

收获园豆:2
碧落星痕 | 小虾三级 |园豆:708 | 2011-12-14 12:16
其他回答(5)
0

这样呢?

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类型由外部赋值。

收获园豆:1
顾晓北 | 园豆:9735 (大侠五级) | 2011-12-14 11:50

由外部赋值的话,外部也肯定会有创建具体类的语句呀,那样还是需要修改,只不过修改外部了

支持(0) 反对(0) cnin | 园豆:172 (初学一级) | 2011-12-14 11:55

@cnin: 我汗,难道你想写一个万能程序不成?开闭原则怎么说的?

支持(0) 反对(0) 顾晓北 | 园豆:9735 (大侠五级) | 2011-12-14 12:56
0
    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();
}
}
收获园豆:1
胡屯 | 园豆:714 (小虾三级) | 2011-12-14 12:28
0

举个例子:

public abstract class Che

{

  public void Drive()

   {

       // 车都可以行驶

    }

     // 但不都可以装货

      public abstract void ZhuangHuo();

}

 

public class Car

{

 // 小汽车不能装货

override ...

}

public class Truck

{

// 大卡车可以装货

override ...

}

家中慢步 | 园豆:218 (菜鸟二级) | 2011-12-14 12:52
0

个人觉得这里可以用个简单工厂

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 都只需要调整工厂类。

希望对你有帮助。

拙见 见笑。

收获园豆:1
菜光 | 园豆:108 (初学一级) | 2011-12-14 13:32
0

可能大家没理解我的意思,我已经找到答案了:

   但事实上我们需要明白,利用抽象的方式封装变化,固然是应对需求变化的王道,但它也仅仅能解除调用者与被调用者相对的耦合关系,只要还涉及到具体对象的创建,即使引入了工厂模式,但具体的工厂对象的创建仍然是必不可少的。那么,对于这样一些业已被封装变化的对象,我们还应该充分利用“依赖注入”的方式来彻底解除两者之间的耦合。(引自张逸大哥的文章)

cnin | 园豆:172 (初学一级) | 2011-12-14 17:34
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册