2013-01-10 17 views
5

Tôi đang xem xét một số mã (Java) và thực hiện các thay đổi dựa trên biểu đồ luồng logic kinh doanh. Mã hiện tại dựa vào một số lượng lớn của câu lệnh if - điều mà tôi muốn thử và chuyển đi. Tôi đã đọc về Đa hình và đang cố gắng quấn quanh đầu tôi để áp dụng nó vào tình huống của tôi. Tôi có thể làm cho nó hoạt động cho một mức điều kiện duy nhất, nhưng phải vật lộn để mở rộng hơn nữa qua nhiều cấp độ có điều kiện. Mã sẽ được thực thi vào thời gian chạy, với phương thức 'Logic' này được chuyển qua các biến từ bước trước đó.Tránh làm tổ nếu khác/công tắc - Java

Ví dụ bị truy tố: Chúng tôi có 2 Sở thú, 'Sở thú A' và 'Sở thú B' và 'Trang chủ'. Mỗi trong số này là một 'Place'. Trong mỗi Sở thú, chúng tôi có 4 'địa điểm', 'Bắc', 'Nam', 'Đông' và 'Tây'. 'Trang chủ' chỉ có một vị trí. Chúng tôi muốn chỉ định 'điểm đến' cho một người ở nơi họ nên đi dựa trên một vài biến. Các biến này là: 'Địa điểm', tương ứng với địa điểm của chúng tôi (Sở thú A, Sở thú B, Nhà riêng). 'Hướng', tương quan với các vị trí của chúng tôi, (N, S, E, W). luồng Chart:

   |----- | 'HOME' 
       |Place?| ----- > *destination = 'home'* 
       |----- | 
    Zoo A   |        Zoo B 
    |---------------|----------------------------------------| 
|----------|          |----------| 
|Direction?|          |Direction?| 
|----------|          |----------| 
    | North           | North 
    ----------- *destination = 'Zoo A North'   ----------- *destination = 'Zoo B North' 
    | East           | East 
    ----------- *destination = 'Zoo A East'    ----------- *destination = 'Zoo B East' 
    | South           | South 
    ----------- *destination = 'Zoo A South'   ----------- *destination = 'Zoo B South' 
    | West           | West 
    ----------- *destination = 'Zoo A West'    ----------- *destination = 'Zoo B West' 

Vì vậy, Nếu Person X có Nơi Zoo A và Hướng Nam họ cần phải có một Điểm đến của 'Zoo Một Nam'

tôi có mã đó là hiện khá xấu xí sử dụng Nếu tuyên bố:

if(Place = 'HOME') 
    destination = 'HOME' 
if(Place = 'Zoo A') 
    if(Direction = North) 
     destination = 'Zoo A North') 
    if(Direct = East) 
     destination = 'Zoo A East') 
    ... 
if(Place = 'Zoo B') 
    if(Direction = North) 
     destination = 'Zoo B North') 
    if(Direct = East) 
     destination = 'Zoo B East') 
    ... 

Tôi có thể biến điều này thành các công tắc lồng nhau với các biến là ENUM. Nhưng tôi đang cố gắng tránh sự phụ thuộc if - else/switch khi tôi có thói quen xấu rơi vào đó. Tôi đã thử nghiệm bằng cách sử dụng Thiết kế Nhà máy để tạo các lớp Địa điểm, sau đó sử dụng Đa hình trên mỗi vị trí và điểm đến nhưng nó bắt đầu trở nên quá phức tạp trong đầu của tôi. Nó thậm chí có giá trị di chuyển ra khỏi nếu/chuyển mạch? Tôi chỉ đang cố gắng hơn để thiết kế nó?

Bất kỳ đề xuất nào về cách xử lý luồng logic như thế này? Cảm ơn

+0

Tôi không hoàn toàn rõ ràng về những gì bạn đang cố gắng làm trong ví dụ của bạn. Chuỗi "Địa điểm" và "Hướng" hay một số loại đối tượng khác? Dù bằng cách nào, một ví dụ đơn giản có thể là tạo các phương thức 'goNorth()', vv trong lớp 'Zoo' của bạn. Tôi không hoàn toàn chắc chắn rằng điều này sẽ giải quyết vấn đề của bạn, tuy nhiên, bởi vì tôi không hoàn toàn rõ ràng về những gì bạn đang cố gắng làm. –

+0

@ Code-Guru - Giả sử chúng là tất cả các chuỗi để đơn giản. Những gì tôi đang cố gắng làm là bắt đầu ở trên cùng của dòng chảy và dựa trên các biến (hướng và địa điểm) kết thúc với một 'đích' cuối cùng. Nhưng trong cách quản lý dễ dàng nhất và dễ bảo trì – NathanS

Trả lời

3

Điều này có thể được mô hình như thế này :

  1. Sử dụng lớp gốc Place, với phương pháp calculateDestination(Person). Địa điểm có thể bao gồm các địa điểm khác bên trong nó.
  2. Tạo Place lớp con cho ZooZooQuadrant (tự nhiên, vì đây là những địa điểm thực).
  3. Các Person đối tượng có giá trị cho currentPlacecurrentDirection

Bây giờ bạn muốn nhanh chóng đối tượng của các lớp này để đại diện cho tình hình của bạn:

zooA = new Zoo("ZooA"); 
zooA.addChild(new ZooQuadrant(Direction.SOUTH)); 
... so on for every quadrant ... 
... same for zooB ... 
home = new Place("Home"); 
world = new Place("World"); 
world.addChild(home); 
world.addChild(zooA); 
world.addChild(zooB); 

Khi bạn muốn để có được đích, bạn sẽ gọi world.calculateDestination(myPerson)

calculateDestination(Person) là phương pháp đa hình. Mỗi cấp trong hệ thống phân cấp thừa kế sẽ ghi đè nó theo các ngữ nghĩa cụ thể của lớp đó.

  1. Place sẽ có một triển khai chung chung rằng sẽ kiểm tra nếu dụ Person hiện đang ở nút đó (bằng cách kiểm tra với giá trị 's Person cho currentPlace) và nếu không, nó sẽ gọi calculateDestination trên mỗi con của nó và trả lại.
  2. Zoo s sẽ cần kiểm tra xem currentPlace == this và nếu có, hãy gọi calculateDestination trên mỗi góc phần tư của nó và kết hợp bất kỳ kết quả tích cực nào với kết quả riêng của mình để trả lại this.name + quadrantResult.
  3. Mỗi ZooQuadrant chỉ cần kiểm tra xem currentDirection có tương đương với hướng của riêng nó không và trả lại giá trị tương ứng.

Lưu ý: đây chỉ là minh họa cách đa hình có thể hoạt động, có thể có triển khai tốt hơn. Ngoài ra, ở đây chúng tôi đang sử dụng cả hai đa hình và đệ quy, hai là độc lập.


EDIT:

Đối dù mức độ phức tạp thêm được bảo đảm, điều đó phụ thuộc! Ở đây chúng tôi đang làm việc với một ví dụ đơn giản với một đồ thị đối tượng là khá nhỏ. Ngay sau khi bạn có hàng chục vườn thú, phải thêm nhiều phần tư hơn trong các vườn thú đó, hoặc cần thêm các quyết định (nếu ví dụ mỗi phần tư có subquadrants), phương thức if-else-if (thủ tục) lồng nhau thực sự lông thực sự nhanh chóng, trong khi phương pháp tiếp cận hướng đối tượng vẫn duy trì và dễ hiểu.

Giống như mọi thứ, nếu bạn thấy trước rằng các quyết định sẽ phức tạp hơn, hãy đi theo phương pháp tiếp cận OO. Nếu không, hãy giữ nó một cách đơn giản, làm đẹp mỗi lần: sử dụng các công cụ thích hợp cho các vấn đề phù hợp.

+0

Cảm ơn bạn đã gợi ý, tôi đã xây dựng một mô hình làm việc này (quá dài để đăng :() Nhìn vào nó Tôi nghĩ rằng tôi chỉ cố gắng làm phức tạp hơn những gì tôi đang làm Nó hoạt động tốt mặc dù! .. – NathanS

0

Một cách tiếp cận là bạn có thể tạo cha mẹ asbtract lớp/giao diện 'Đặt' với phương thức getNorthDestination(), getEastDestination() v.v.

Sau đó, bạn tạo một lớp con/thực hiện 'Đặt' gọi 'ZooA' và 'ZooB', và ghi đè/thực hiện các phương pháp getXXXDestination() để trở về vị trí

+0

sẽ có nhiều công việc hơn để duy trì, cho biết thêm hướng Đông Nam, Lên, Xuống, bạn sẽ phải có thêm phương pháp ở nhiều nơi. – BevynQ

+0

Đó là những gì tôi muốn tránh, là những thay đổi trong tương lai có thể thêm một Zoo mới, hoặc một hướng mới mà không phá vỡ logic. @ gerrytan - Đó là một ý tưởng tốt, nó sẽ giới hạn khối nếu 'if (Place place = Zoo A) trả về Place = new Zoo A' ... sau đó chỉ cần gọi một switch trên Direction,' case North: place.goNorth(); '. Có đúng không? – NathanS

0

tương ứng Từ này tôi thấy ít nhất ba lớp bạn muốn là Địa điểm, Chỉ đường và Điểm đến.

Địa điểm sẽ có thuộc tính tên và phương thức getName() tên được đặt thành Sở thú A, Sở thú B, Trang chủ.

Bạn sẽ đặt Lớp con về nhà và vườn thú của Địa điểm nếu chúng có hành vi khác nhau. Trong trường hợp này, bạn có thể làm điều đó bởi vì Trang chủ không có hướng nhưng Sở thú có.

Hướng có thể là một enum (chỉ là một loại đặc biệt của lớp) có chứa Bắc, Đông, Tây, Nam.

Điểm đến sẽ có hai thuộc tính là Địa điểm và Chỉ đường. Nó cũng sẽ có phương thức getDestination()

public String getDestination(){ 
    if (this.direction == null){ 
     result = this.place.getName(); 
    } else { 
     result = this.place.getName() + " " + this.direction.getName(); 
    } 
    return result; 
} 
0

Đi kèm với câu trả lời của gerrytan. Đối với mỗi phần thông tin, bạn nên tự hỏi mình, "tôi thực sự cần một lớp học cho điều này?". Nhiều lần, câu trả lời là không. Chuỗi đơn giản/biến số đủ.Bây giờ, bạn muốn ghép nối các biến này với các phương thức getter/setter, vì đây là những gì java nhấn mạnh vào, trái ngược với việc tham chiếu các biến công khai trực tiếp (như C++). Việc tham chiếu các phương thức đơn giản dễ hơn rất nhiều so với việc kiểm tra ví dụ.

0

bạn có thể tạo ra một phương pháp mới với Zoo A và B Sở thú ở trong đó ...... bạn có thể gọi nó như directionForZoo(), và nếu thử sử dụng vòng lặp while

0

Nếu bạn không muốn quá kỹ sư, giải pháp sau đây sẽ là giải pháp đơn giản để loại bỏ nếu có. Nhưng nó không phải là một cách tiếp cận thanh lịch.

Bạn có thể có bản đồ trong đó các phím là (Place + Direction) và các giá trị là Điểm đến tương ứng. Điều này chỉ tốt nếu giá trị Place và Direction giống như tĩnh tại thời điểm này trong chương trình của bạn và nó không có khả năng thay đổi nhiều.

Ví dụ: lưu trữ địa điểm của mình và đích tương ứng trong một bản đồ

Map<String, String> destMap = new HashMap<String, String>(); 
destMap.put("HOME","HOME"); 
destMap.put("Zoo A+North","Zoo A North"); 
destMap.put("Zoo A+East","Zoo A East"); 
destMap.put("Zoo B+North","Zoo B North"); 

Lấy điểm đến theo Place và Hướng:

destMap.get(Place + "+" + Direction); 
0

Một giải pháp khả thi để ví dụ của bạn là tạo ra một (có thể trừu tượng) Location lớp. Điều này có thể chứa một cấu trúc dữ liệu cho các điểm đến của bạn. Một khả năng cho cấu trúc dữ liệu này có lẽ là Map<Direction, Location>) trong đó Direction là một enum có thể được sử dụng làm khóa để ánh xạ tới đối tượng Location là đích đến theo hướng đó. Bạn có thể phân lớp Location để tạo các lớp Home, Zoo, v.v. hoặc bạn có thể cung cấp trường name khác biệt với Location s. Hoặc bạn có thể làm một số kết hợp của cả hai.

Lưu ý rằng đây là thiết kế nửa nướng có thể hoặc không thể đáp ứng nhu cầu của bạn. Thiết kế OO tốt có kinh nghiệm và kiến ​​thức chi tiết về các yêu cầu chính xác cho vấn đề bạn đang cố gắng giải quyết. Tôi có một số hiểu biết trước đây nhưng rất ít về sau này.

0

Tôi đã thử một biến thể trên một vài câu trả lời được đề xuất.

Tôi đã kết thúc bằng cách sử dụng khối trường hợp chuyển đổi lồng nhau. Không phải là lý tưởng nhất và những gì tôi muốn tránh nhưng cho mục đích của tôi nó dễ bảo trì hơn (nó sẽ không thay đổi hoặc được mở rộng).

Tôi sẽ đánh dấu phương pháp @Ezequiel Muns là chính xác khi phiên bản của tôi hoạt động rất tốt - không chỉ là điều cần thiết cho vấn đề.

Cảm ơn tất cả sự trợ giúp.

Các vấn đề liên quan