Monday, December 17, 2012

OOP


先看这篇教程是怎么来讲述OOP的。它先给了下面这个问题,这个问题需要输出一段关于操作系统的文字:假设Unix很不错,Windows很差。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class PrintOS
{
    public static void main(final String[] args)
    {
        String osName = System.getProperty("os.name") ;
        if (osName.equals("SunOS") || osName.equals("Linux"))
        {
            System.out.println("This is a UNIX box and therefore good.") ;
        }
        else if (osName.equals("Windows NT") || osName.equals("Windows 95"))
        {
            System.out.println("This is a Windows box and therefore bad.") ;
        }
        else
        {
            System.out.println("This is not a box.") ;
        }
    }
}
然后开始用面向对象的编程方式一步一步地进化这个代码。
先是以过程化的思路来重构之。

过程化的方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class PrintOS
{
    private static String unixBox()
    {
        return "This is a UNIX box and therefore good." ;
    }
    private static String windowsBox()
    {
        return "This is a Windows box and therefore bad." ;
    }
    private static String defaultBox()
    {
        return "This is not a box." ;
    }
    private static String getTheString(final String osName)
    {
        if (osName.equals("SunOS") || osName.equals("Linux"))
        {
            return unixBox() ;
        }
        else if (osName.equals("Windows NT") ||osName.equals("Windows 95"))
        {
            return windowsBox() ;
        }
        else
        {
            return defaultBox() ;
        }
    }
    public static void main(final String[] args)
    {
        System.out.println(getTheString(System.getProperty("os.name"))) ;
    }
}
然后是一个幼稚的面向对象的思路。

幼稚的面向对象编程

PrintOS.java
1
2
3
4
5
6
7
public class PrintOS
{
    public static void main(final String[] args)
    {
        System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;
    }
}

OSDiscriminator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class OSDiscriminator // Factory Pattern
{
    private static BoxSpecifier theBoxSpecifier = null ;
    public static BoxSpecifier getBoxSpecifier()
    {
        if (theBoxSpecifier == null)
        {
            String osName = System.getProperty("os.name") ;
            if (osName.equals("SunOS") || osName.equals("Linux"))
            {
                theBoxSpecifier = new UNIXBox() ;
            }
            else if (osName.equals("Windows NT") || osName.equals("Windows 95"))
            {
                theBoxSpecifier = new WindowsBox() ;
            }
            else
            {
                theBoxSpecifier = new DefaultBox () ;
            }
        }
        return theBoxSpecifier ;
    }
}

BoxSpecifier.java
1
2
3
4
public interface BoxSpecifier
{
    String getStatement() ;
}

DefaultBox.java
1
2
3
4
5
6
7
public class DefaultBox implements BoxSpecifier
{
    public String getStatement()
    {
        return "This is not a box." ;
    }
}

UNIXBox.java
1
2
3
4
5
6
7
public class UNIXBox implements BoxSpecifier
{
    public String getStatement()
    {
        return "This is a UNIX box and therefore good." ;
    }
}

WindowsBox.java
1
2
3
4
5
6
7
public class WindowsBox implements BoxSpecifier
{
    public String getStatement()
    {
        return "This is a Windows box and therefore bad." ;
    }
}
他们觉得上面这段代码没有消除if语句,他们说这叫代码的“logic bottleneck”(逻辑瓶颈),因为如果你要增加一个操作系统的判断的话,你不但要加个类,还要改那段if-else的语句。
所以,他们整出一个叫Sophisticated的面向对象的解决方案。

OO大师的方案

注意其中的Design Pattern
PrintOS.java
1
2
3
4
5
6
7
public class PrintOS
{
    public static void main(final String[] args)
    {
        System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;
    }
}
OSDiscriminator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class OSDiscriminator // Factory Pattern
{
    private static java.util.HashMap storage = new java.util.HashMap() ;
 
    public static BoxSpecifier getBoxSpecifier()
    {
        BoxSpecifier value = (BoxSpecifier)storage.get(System.getProperty("os.name")) ;
        if (value == null)
            return DefaultBox.value ;
        return value ;
    }
    public static void register(final String key, final BoxSpecifier value)
    {
        storage.put(key, value) ; // Should guard against null keys, actually.
    }
    static
    {
        WindowsBox.register() ;
        UNIXBox.register() ;
        MacBox.register() ;
    }
}
BoxSpecifier.java
1
2
3
4
public interface BoxSpecifier
{
    String getStatement() ;
}
DefaultBox.java
1
2
3
4
5
6
7
8
9
public class DefaultBox implements BoxSpecifier // Singleton Pattern
{
    public static final DefaultBox value = new DefaultBox () ;
    private DefaultBox() { }
    public String getStatement()
    {
        return "This is not a box." ;
    }
}
UNIXBox.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UNIXBox implements BoxSpecifier // Singleton Pattern
{
    public static final UNIXBox value = new UNIXBox() ;
    private UNIXBox() { }
    public  String getStatement()
    {
        return "This is a UNIX box and therefore good." ;
    }
    public static final void register()
    {
        OSDiscriminator.register("SunOS", value) ;
        OSDiscriminator.register("Linux", value) ;
    }
}
WindowsBox.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class WindowsBox implements BoxSpecifier  // Singleton Pattern
{
    public  static final WindowsBox value = new WindowsBox() ;
    private WindowsBox() { }
    public String getStatement()
    {
        return "This is a Windows box and therefore bad." ;
    }
    public static final void register()
    {
        OSDiscriminator.register("Windows NT", value) ;
        OSDiscriminator.register("Windows 95", value) ;
    }
}
MacBox.java
1
2
3
4
5
6
7
8
9
10
11
12
13
public class MacBox implements BoxSpecifier // Singleton Pattern
{
    public static final MacBox value = new MacBox() ;
    private MacBox() { }
    public  String getStatement()
    {
        return "This is a Macintosh box and therefore far superior." ;
    }
    public static final void register()
    {
        OSDiscriminator.register("Mac OS", value) ;
    }
}

No comments:

Post a Comment