Có một mẫu thiết kế để loại bỏ sự cần thiết phải kiểm tra cờ?


28

Tôi sẽ lưu một số tải trọng chuỗi trong cơ sở dữ liệu. Tôi có hai cấu hình toàn cầu:

  • mã hóa
  • nén

Chúng có thể được bật hoặc tắt bằng cách sử dụng cấu hình theo cách chỉ một trong số chúng được bật, cả hai đều được bật hoặc cả hai đều bị tắt.

Triển khai hiện tại của tôi là thế này:

if (encryptionEnable && !compressEnable) {
    encrypt(data);
} else if (!encryptionEnable && compressEnable) {
    compress(data);
} else if (encryptionEnable && compressEnable) {
    encrypt(compress(data));
} else {
  data;
}

Tôi đang nghĩ về mẫu trang trí. Đó có phải là lựa chọn đúng đắn, hoặc có lẽ có một sự thay thế tốt hơn?


5
Có gì sai với những gì bạn hiện đang có? Là các yêu cầu có khả năng thay đổi cho chức năng này? IE, có khả năng sẽ có iftuyên bố mới ?
Darren Young

Không, tôi đang xem bất kỳ giải pháp nào khác để cải thiện mã.
Damith Ganegoda

46
Bạn đang đi về phía sau này. Bạn không tìm thấy một mẫu sau đó viết mã để phù hợp với mẫu đó. Bạn viết mã để phù hợp với yêu cầu của bạn, sau đó tùy ý sử dụng một mẫu để mô tả mã của bạn.
Cuộc đua nhẹ nhàng với Monica

1
lưu ý nếu bạn tin rằng câu hỏi của bạn thực sự là một bản sao của câu hỏi này , thì với tư cách là người hỏi, bạn có một tùy chọn để "ghi đè" mở lại gần đây và tự tay đóng nó như vậy. Tôi đã làm điều đó với một số câu hỏi của riêng tôi và nó hoạt động như một cơ duyên. Đây là cách tôi đã thực hiện, 3 bước đơn giản - sự khác biệt duy nhất với "hướng dẫn" của tôi là vì bạn có ít hơn 3K đại diện, bạn sẽ phải đi qua hộp thoại cờ để đến tùy chọn "trùng lặp"
gnat

8
@LightnessRacesinOrbit: Có một số sự thật trong những gì bạn nói, nhưng hoàn toàn hợp lý để hỏi liệu có cách nào tốt hơn để cấu trúc mã của một người hay không, và hoàn toàn hợp lý khi gọi một mẫu thiết kế để mô tả một cấu trúc tốt hơn được đề xuất. (Tuy nhiên, tôi đồng ý rằng đó là một vấn đề XY khi yêu cầu một mẫu thiết kế khi những gì bạn muốn là một thiết kế , có thể hoặc không tuân thủ nghiêm ngặt bất kỳ mẫu nổi tiếng nào.) Ngoài ra, nó hợp pháp cho "mẫu" ảnh hưởng đến mã của bạn một chút, trong đó nếu bạn đang sử dụng một mẫu nổi tiếng, việc đặt tên cho các thành phần của bạn theo đó là hợp lý.
ruakh

Câu trả lời:


15

Khi thiết kế mã, bạn có thể có hai lựa chọn.

  1. chỉ cần hoàn thành nó, trong trường hợp đó, mọi giải pháp sẽ giúp ích cho bạn
  2. mang tính mô phạm và thiết kế một giải pháp khai thác các yêu cầu của ngôn ngữ theo ý thức hệ của nó (ngôn ngữ OO trong trường hợp này - sử dụng đa hình như một phương tiện để đưa ra quyết định)

Tôi sẽ không tập trung vào phần đầu tiên của hai người, bởi vì thực sự không có gì để nói. Nếu bạn chỉ muốn làm cho nó hoạt động, bạn có thể để lại mã như vậy.

Nhưng điều gì sẽ xảy ra, nếu bạn chọn thực hiện theo cách mô phạm và thực sự giải quyết vấn đề với các mẫu thiết kế, theo cách bạn muốn nó làm?

Bạn có thể xem xét quy trình sau:

Khi thiết kế mã OO, hầu hết các ifmã trong mã không phải ở đó. Đương nhiên, nếu bạn muốn so sánh hai loại vô hướng, chẳng hạn như ints hoặc floats, bạn có khả năng có một if, nhưng nếu bạn muốn thay đổi quy trình dựa trên cấu hình, bạn có thể sử dụng đa hình để đạt được những gì bạn muốn, di chuyển các quyết định ( ifs) từ logic kinh doanh của bạn đến một nơi, nơi các đối tượng được khởi tạo - đến các nhà máy .

Đến bây giờ, quy trình của bạn có thể đi qua 4 đường dẫn riêng biệt:

  1. datakhông được mã hóa hay nén (gọi không có gì, trả lại data)
  2. datađược nén (gọi compress(data)và trả lại)
  3. datađược mã hóa (gọi encrypt(data)và trả lại)
  4. datađược nén và mã hóa (gọi encrypt(compress(data))và trả lại)

Chỉ cần nhìn vào 4 con đường, bạn tìm thấy một vấn đề.

Bạn có một quy trình gọi 3 (theo lý thuyết là 4, nếu bạn không gọi bất kỳ thứ gì là một) các phương thức khác nhau thao túng dữ liệu và sau đó trả về nó. Các phương thức có các tên khác nhau , khác nhau được gọi là API công khai (cách thức mà các phương thức truyền đạt hành vi của chúng).

Sử dụng mẫu bộ điều hợp , chúng tôi có thể giải quyết colision tên (chúng tôi có thể hợp nhất API công khai) đã xảy ra. Nói một cách đơn giản, bộ chuyển đổi giúp hai giao diện không tương thích làm việc cùng nhau. Ngoài ra, bộ điều hợp hoạt động bằng cách xác định giao diện bộ điều hợp mới, mà các lớp đang cố gắng hợp nhất triển khai API của chúng.

Đây không phải là một ngôn ngữ cụ thể. Đó là một cách tiếp cận chung chung, bất kỳ từ khóa nào ở đó để thể hiện nó có thể thuộc bất kỳ loại nào, trong một ngôn ngữ như C #, bạn có thể thay thế nó bằng generic ( <T>).

Tôi sẽ giả định rằng, ngay bây giờ bạn có thể có hai lớp chịu trách nhiệm nén và mã hóa.

class Compression
{
    Compress(data : any) : any { ... }
}

class Encryption
{
    Encrypt(data : any) : any { ... }
}

Trong thế giới doanh nghiệp, ngay cả các lớp cụ thể này rất có thể bị thay thế bởi các giao diện, chẳng hạn như classtừ khóa sẽ được thay thế bằng interface(bạn nên xử lý các ngôn ngữ như C #, Java và / hoặc PHP) hoặc classtừ khóa sẽ ở lại, nhưng CompressEncryptcác phương thức sẽ được định nghĩa là ảo thuần , nếu bạn viết mã bằng C ++.

Để tạo một bộ chuyển đổi, chúng tôi xác định một giao diện chung.

interface DataProcessing
{
    Process(data : any) : any;
}

Sau đó, chúng tôi phải cung cấp các triển khai của giao diện để làm cho nó hữu ích.

// when neither encryption nor compression is enabled
class DoNothingAdapter : DataProcessing
{
    public Process(data : any) : any
    {
        return data;
    }
}

// when only compression is enabled
class CompressionAdapter : DataProcessing
{
    private compression : Compression;

    public Process(data : any) : any
    {
        return this.compression.Compress(data);
    }
}

// when only encryption is enabled
class EncryptionAdapter : DataProcessing
{
    private encryption : Encryption;

    public Process(data : any) : any
    {
        return this.encryption.Encrypt(data);
    }
}

// when both, compression and encryption are enabled
class CompressionEncryptionAdapter : DataProcessing
{
    private compression : Compression;
    private encryption : Encryption;

    public Process(data : any) : any
    {
        return this.encryption.Encrypt(
            this.compression.Compress(data)
        );
    }
}

Bằng cách này, bạn kết thúc với 4 lớp, mỗi lớp làm một thứ hoàn toàn khác nhau, nhưng mỗi lớp cung cấp cùng một API công khai. Các Processphương pháp.

Trong logic kinh doanh của bạn, nơi bạn xử lý quyết định không / mã hóa / nén / cả hai, bạn sẽ thiết kế đối tượng của mình để làm cho nó phụ thuộc vào DataProcessinggiao diện mà chúng ta đã thiết kế trước đó.

class DataService
{
    private dataProcessing : DataProcessing;

    public DataService(dataProcessing : DataProcessing)
    {
        this.dataProcessing = dataProcessing;
    }
}

Quá trình tự nó có thể đơn giản như thế này:

public ComplicatedProcess(data : any) : any
{
    data = this.dataProcessing.Process(data);

    // ... perhaps work with the data

    return data;
}

Không còn điều kiện nữa. Lớp DataServicekhông biết điều gì sẽ thực sự được thực hiện với dữ liệu khi nó được chuyển cho dataProcessingthành viên và nó không thực sự quan tâm đến nó, đó không phải là trách nhiệm của nó.

Lý tưởng nhất là bạn sẽ có các bài kiểm tra đơn vị kiểm tra 4 lớp bộ điều hợp bạn đã tạo để đảm bảo chúng hoạt động, bạn thực hiện bài kiểm tra của mình. Và nếu họ vượt qua, bạn có thể khá chắc chắn rằng họ sẽ làm việc bất kể bạn gọi họ ở đâu trong mã của bạn.

Vì vậy, làm theo cách này tôi sẽ không bao giờ có ifs trong mã của mình nữa?

Không. Bạn ít có điều kiện trong logic kinh doanh của mình, nhưng họ vẫn phải ở đâu đó. Nơi là nhà máy của bạn.

Và điều này là tốt. Bạn tách các mối quan tâm của việc tạo và thực sự sử dụng mã. Nếu bạn làm cho các nhà máy của mình trở nên đáng tin cậy (bằng Java, bạn thậm chí có thể sử dụng một cái gì đó giống như khung Guice của Google), theo logic kinh doanh của bạn, bạn không lo lắng về việc chọn đúng loại được tiêm. Bởi vì bạn biết các nhà máy của bạn làm việc và sẽ cung cấp những gì được yêu cầu.

Có cần thiết phải có tất cả các lớp, giao diện, vv?

Điều này đưa chúng ta trở lại sự khởi đầu.

Trong OOP, nếu bạn chọn đường dẫn sử dụng đa hình, thực sự muốn sử dụng các mẫu thiết kế, muốn khai thác các tính năng của ngôn ngữ và / hoặc muốn theo mọi thứ là một ý thức hệ đối tượng, thì đó là. Và thậm chí sau đó, ví dụ này thậm chí không hiển thị tất cả các nhà máy bạn sẽ cần và nếu bạn đã cấu trúc lại các CompressionEncryptioncác lớp học và làm cho họ giao diện thay vào đó, bạn phải bao gồm việc triển khai của họ là tốt.

Cuối cùng, bạn kết thúc với hàng trăm lớp học và giao diện nhỏ, tập trung vào những thứ rất cụ thể. Điều này không hẳn là xấu, nhưng có thể không phải là giải pháp tốt nhất cho bạn nếu tất cả những gì bạn muốn là làm một việc đơn giản như thêm hai số.

Nếu bạn muốn làm cho nó thực hiện và nhanh chóng, bạn có thể lấy giải pháp Ixrec của , người ít nhất được quản lý để loại bỏ else ifelsengăn chặn, trong đó, theo ý kiến của tôi, thậm chí còn tồi tệ hơn một chút so với một đồng bằng if.

Hãy xem xét đây là cách của tôi để làm cho thiết kế OO tốt. Viết mã cho các giao diện thay vì triển khai, đây là cách tôi đã thực hiện trong vài năm qua và đó là cách tiếp cận tôi cảm thấy thoải mái nhất.

Cá nhân tôi thích lập trình if-less hơn và sẽ đánh giá cao giải pháp dài hơn trong 5 dòng mã. Đó là cách tôi quen với việc thiết kế mã và rất thoải mái khi đọc nó.


Cập nhật 2: Đã có một cuộc thảo luận sôi nổi về phiên bản đầu tiên của giải pháp của tôi. Thảo luận chủ yếu là do tôi, mà tôi xin lỗi.

Tôi quyết định chỉnh sửa câu trả lời theo cách đó là một trong những cách để xem xét giải pháp nhưng không phải là cách duy nhất. Tôi cũng loại bỏ phần trang trí, thay vào đó tôi có nghĩa là mặt tiền, mà cuối cùng tôi quyết định bỏ đi hoàn toàn, bởi vì một bộ chuyển đổi là một biến thể mặt tiền.


28
Tôi đã không downvote nhưng lý do có thể là số lượng lớn các lớp / giao diện mới để làm một cái gì đó mà mã gốc đã làm trong 8 dòng (và câu trả lời khác đã làm trong 5). Theo tôi, điều duy nhất nó đạt được là tăng thời gian học tập cho mã.
Maurycy

6
@Maurycy Điều OP yêu cầu là cố gắng tìm giải pháp cho vấn đề của mình bằng cách sử dụng các mẫu thiết kế chung, nếu giải pháp đó tồn tại. Là giải pháp của tôi dài hơn mã của anh ấy hoặc Ixrec? Nó là. Tôi thừa nhận rằng. Liệu giải pháp của tôi có giải quyết được vấn đề của anh ấy bằng cách sử dụng các mẫu thiết kế và do đó trả lời câu hỏi của anh ấy và cũng loại bỏ hiệu quả tất cả các if cần thiết khỏi quy trình không? Nó làm. Ixrec không.
Andy

26
Tôi tin rằng viết mã rõ ràng, đáng tin cậy, súc tích, thực hiện và duy trì là cách để đi. Nếu tôi có một đô la cho mỗi lần ai đó trích dẫn RẮN hoặc trích dẫn một mẫu phần mềm mà không nói rõ mục tiêu và lý do của họ, tôi sẽ là một người giàu có.
Robert Harvey

12
Tôi nghĩ rằng tôi có hai vấn đề tôi thấy ở đây. Đầu tiên là Compressionvà các Encryptiongiao diện dường như hoàn toàn thừa. Tôi không chắc chắn nếu bạn đề xuất rằng chúng bằng cách nào đó cần thiết cho quá trình trang trí, hoặc chỉ ngụ ý rằng chúng đại diện cho các khái niệm được trích xuất. Vấn đề thứ hai là việc tạo ra một lớp giống như CompressionEncryptionDecoratordẫn đến một vụ nổ tổ hợp giống như điều kiện của OP. Tôi cũng không thấy mẫu trang trí đủ rõ ràng trong mã được đề xuất.
cbojar

5
Cuộc tranh luận về RẮN so với đơn giản là thiếu điểm chính: mã này là không, và nó cũng không sử dụng mẫu trang trí. Mã không tự động RẮN chỉ vì nó sử dụng một loạt các giao diện. Sự phụ thuộc vào giao diện DataProcessing là khá tốt; mọi thứ khác là thừa. RẮN là một mối quan tâm cấp kiến ​​trúc nhằm xử lý thay đổi tốt. OP không đưa ra thông tin nào về kiến ​​trúc của anh ấy cũng như cách anh ấy hy vọng mã của mình thay đổi, vì vậy chúng tôi thậm chí không thể thảo luận về RẮN trong câu trả lời.
Carl Leth

120

Vấn đề duy nhất tôi thấy với mã hiện tại của bạn là nguy cơ bùng nổ tổ hợp khi bạn thêm nhiều cài đặt, có thể dễ dàng giảm thiểu bằng cách cấu trúc mã giống như sau:

if(compressEnable){
  data = compress(data);
}
if(encryptionEnable) {
  data = encrypt(data);
}
return data;

Tôi không biết về bất kỳ "mẫu thiết kế" hay "thành ngữ" nào mà đây có thể được coi là một ví dụ về.


18
@DamithGanegoda Không, nếu bạn đọc kỹ mã của tôi, bạn sẽ thấy nó thực hiện chính xác điều tương tự trong trường hợp đó. Đó là lý do tại sao không có elsegiữa hai câu lệnh if của tôi và tại sao tôi lại gán cho datamỗi lần. Nếu cả hai cờ đều đúng, thì nén () được thực thi, sau đó mã hóa () được thực thi trên kết quả của nén (), giống như bạn muốn.
Ixrec

14
@DavidPacker Về mặt kỹ thuật, câu lệnh if trong mọi ngôn ngữ lập trình cũng vậy. Tôi đã đi cho đơn giản, vì điều này trông giống như một vấn đề trong đó một câu trả lời rất đơn giản là phù hợp. Giải pháp của bạn cũng hợp lệ, nhưng cá nhân tôi sẽ lưu nó khi tôi có nhiều hơn hai cờ boolean để lo lắng.
Ixrec

15
@DavidPacker: chính xác không được xác định bởi mức độ tuân thủ mã theo một số hướng dẫn của một số tác giả về một số ý thức hệ lập trình. Đúng là "mã có làm những gì nó phải làm và nó đã được thực hiện trong một khoảng thời gian hợp lý". Nếu nó có ý nghĩa để làm điều đó "sai cách", thì cách sai là cách đúng vì thời gian là tiền bạc.
tên của

9
@DavidPacker: Nếu tôi ở vị trí của OP và hỏi câu hỏi đó, Lightness Race trong bình luận của Orbit là thứ tôi thực sự cần. "Tìm giải pháp sử dụng các mẫu thiết kế" đã bắt đầu từ chân sai.
tên của

6
@DavidPacker Trên thực tế nếu bạn đọc câu hỏi kỹ hơn, nó không nhấn mạnh vào một mẫu. Nó nói, "Tôi đang nghĩ về mẫu Trang trí. Đây có phải là lựa chọn đúng đắn, hoặc có lẽ có một sự thay thế tốt hơn?" . Bạn đã giải quyết câu đầu tiên trong trích dẫn của tôi, nhưng không phải câu thứ hai. Những người khác đã tiếp cận rằng không, đó không phải là lựa chọn đúng đắn. Sau đó, bạn không thể tuyên bố rằng chỉ có bạn trả lời câu hỏi.
Jon Bentley

12

Tôi đoán câu hỏi của bạn không phải là thực tế, trong trường hợp đó câu trả lời của lxrec là câu trả lời đúng, nhưng để tìm hiểu về các mẫu thiết kế.

Rõ ràng mẫu lệnh là một sự quá mức cho một vấn đề tầm thường như vấn đề bạn đề xuất nhưng vì mục đích minh họa ở đây:

public interface Command {
    public String transform(String s);
}

public class CompressCommand implements Command {
    @Override
    public String transform(String s) {
        String compressedString=null;
        //Compression code here
        return compressedString;
    }
}

public class EncryptCommand implements Command {
    @Override
    public String transform(String s) {
        String EncrytedString=null;
        // Encryption code goes here
        return null;
    }

}

public class Test {
    public static void main(String[] args) {
        List<Command> commands = new ArrayList<Command>();
        commands.add(new CompressCommand());
        commands.add(new EncryptCommand()); 
        String myString="Test String";
        for (Command c: commands){
            myString = c.transform(myString);
        }
        // now myString can be stored in the database
    }
}

Như bạn thấy việc đặt các lệnh / chuyển đổi trong một danh sách cho phép có thể được thực hiện tuần tự. Rõ ràng là nó sẽ thực thi cả hai, hoặc chỉ một trong số chúng phụ thuộc vào những gì bạn đưa vào danh sách mà không có điều kiện.

Rõ ràng các điều kiện sẽ kết thúc trong một số loại nhà máy tập hợp danh sách lệnh.

EDIT cho bình luận của @ texacre:

Có nhiều cách để tránh các điều kiện if trong phần sáng tạo của giải pháp, ví dụ như ứng dụng GUI trên máy tính để bàn . Bạn có thể có các hộp kiểm cho các tùy chọn nén và mã hóa. Trong trường on clichợp các hộp kiểm đó, bạn khởi tạo lệnh tương ứng và thêm nó vào danh sách hoặc xóa khỏi danh sách nếu bạn bỏ chọn tùy chọn.


Trừ khi bạn có thể cung cấp một ví dụ về "một số loại nhà máy tập hợp danh sách lệnh" mà không có mã về cơ bản giống như câu trả lời của Ixrec thì IMO, điều này không trả lời câu hỏi. Điều này cung cấp một cách tốt hơn để thực hiện các chức năng nén và mã hóa, nhưng không phải là cách tránh các cờ.
thexacre

@thexacre Tôi đã thêm một ví dụ.
Tulains Córdova

Vì vậy, trong hộp kiểm sự kiện người nghe của bạn, bạn có "if box.ticky rồi thêm lệnh"? Đối với tôi có vẻ như bạn chỉ xáo trộn cờ nếu phát biểu xung quanh ...
thexacre

@thexacre Không, một người nghe cho mỗi hộp kiểm. Trong sự kiện bấm chỉ commands.add(new EncryptCommand()); hoặc commands.add(new CompressCommand());tương ứng.
Tulains Córdova

Điều gì về việc xử lý bỏ chọn hộp? Chỉ trong mỗi bộ công cụ ngôn ngữ / giao diện người dùng tôi đã gặp, bạn vẫn cần kiểm tra trạng thái của hộp kiểm trong trình nghe sự kiện. Tôi đồng ý rằng đây là một mô hình tốt hơn, nhưng về cơ bản, nó không cần phải làm gì nếu cờ làm điều gì đó ở đâu đó.
thexacre

7

Tôi nghĩ rằng "các mẫu thiết kế" không nhất thiết hướng đến "các mẫu oo" và hoàn toàn tránh các ý tưởng đơn giản hơn nhiều. Những gì chúng ta đang nói ở đây là một đường ống dữ liệu (đơn giản).

Tôi sẽ cố gắng làm điều đó trong clojure. Bất kỳ ngôn ngữ nào khác có chức năng là hạng nhất cũng có thể là tốt. Có lẽ tôi có thể làm ví dụ về C # sau này, nhưng nó không hay bằng. Cách giải quyết của tôi sẽ là các bước sau đây với một số giải thích cho những người không phải là người clojurian:

1. Đại diện cho một tập hợp các biến đổi.

(def transformations { :encrypt  (fn [data] ... ) 
                       :compress (fn [data] ... )})

Đây là bản đồ, tức là bảng tra cứu / từ điển / bất cứ thứ gì, từ từ khóa đến chức năng. Một ví dụ khác (từ khóa đến chuỗi):

(def employees { :A1 "Alice" 
                 :X9 "Bob"})

(employees :A1) ; => "Alice"
(:A1 employees) ; => "Alice"

Vì vậy, viết (transformations :encrypt)hoặc (:encrypt transformations)sẽ trả lại chức năng mã hóa. ( (fn [data] ... )chỉ là một hàm lambda.)

2. Nhận các tùy chọn dưới dạng một chuỗi các từ khóa:

(defn do-processing [options data] ;function definition
  ...)

(do-processing [:encrypt :compress] data) ;call to function

3. Lọc tất cả các biến đổi bằng cách sử dụng các tùy chọn được cung cấp.

(let [ transformations-to-run (map transformations options)] ... )

Thí dụ:

(map employees [:A1]) ; => ["Alice"]
(map employees [:A1 :X9]) ; => ["Alice", "Bob"]

4. Kết hợp các chức năng thành một:

(apply comp transformations-to-run)

Thí dụ:

(comp f g h) ;=> f(g(h()))
(apply comp [f g h]) ;=> f(g(h()))

5. Và sau đó cùng nhau:

(def transformations { :encrypt  (fn [data] ... ) 
                       :compress (fn [data] ... )})

(defn do-processing [options data]
  (let [transformations-to-run (map transformations options)
        selected-transformations (apply comp transformations-to-run)] 
    (selected-transformations data)))

(do-processing [:encrypt :compress])

CHỈ thay đổi nếu chúng ta muốn thêm một chức năng mới, giả sử "debug-print", như sau:

(def transformations { :encrypt  (fn [data] ... ) 
                       :compress (fn [data] ... )
                       :debug-print (fn [data] ...) }) ;<--- here to add as option

(defn do-processing [options data]
  (let [transformations-to-run (map transformations options)
        selected-transformations (apply comp transformations-to-run)] 
    (selected-transformations data)))

(do-processing [:encrypt :compress :debug-print]) ;<-- here to use it
(do-processing [:compress :debug-print]) ;or like this
(do-processing [:encrypt]) ;or like this

Làm thế nào các func được điền để chỉ bao gồm các hàm cần được áp dụng mà không cần sử dụng một loạt các câu lệnh if theo cách này hay cách khác?
thexacre

Hàng funcs-to-run-here (map options funcs)đang thực hiện quá trình lọc, do đó chọn một tập hợp các hàm để áp dụng. Có lẽ tôi nên cập nhật câu trả lời và đi vào chi tiết hơn một chút.
NiklasJ

5

[Về cơ bản, câu trả lời của tôi là phần tiếp theo cho câu trả lời của @Ixrec ở trên . ]

Một câu hỏi quan trọng: số lượng kết hợp riêng biệt mà bạn cần bao gồm sẽ tăng lên? Bạn nhận thức rõ hơn về lĩnh vực chủ đề của bạn. Đây là phán đoán của bạn để thực hiện.
Số lượng các biến thể có thể phát triển? Chà, điều đó không thể tưởng tượng được. Ví dụ, bạn có thể cần phải chứa nhiều thuật toán mã hóa khác nhau.

Nếu bạn dự đoán rằng số lượng kết hợp riêng biệt sẽ tăng lên, thì mẫu Chiến lược có thể giúp bạn. Nó được thiết kế để đóng gói các thuật toán và cung cấp giao diện có thể hoán đổi cho mã gọi. Bạn vẫn sẽ có một lượng logic nhỏ khi bạn tạo (khởi tạo) chiến lược phù hợp cho từng chuỗi cụ thể.

Bạn đã nhận xét ở trên rằng bạn không mong đợi các yêu cầu thay đổi. Nếu bạn không mong đợi rằng số lượng biến thể sẽ tăng lên (hoặc nếu bạn có thể trì hoãn việc tái cấu trúc này), thì hãy giữ nguyên logic như hiện tại. Hiện tại, bạn có một lượng logic nhỏ và có thể quản lý được. (Có thể đặt một ghi chú cho bản thân trong các nhận xét về khả năng tái cấu trúc cho mẫu Chiến lược.)


1

Một cách để làm điều này trong scala sẽ là:

val handleCompression: AnyRef => AnyRef = data => if (compressEnable) compress(data) else data
val handleEncryption: AnyRef => AnyRef = data => if (encryptionEnable) encrypt(data) else data
val handleData = handleCompression andThen handleEncryption
handleData(data)

Sử dụng mô hình trang trí để đạt được các mục tiêu trên (tách logic xử lý riêng lẻ và cách chúng kết nối với nhau) sẽ quá dài dòng.

Trong đó bạn sẽ yêu cầu một mẫu thiết kế để đạt được các mục tiêu thiết kế này trong mô hình lập trình OO, ngôn ngữ chức năng cung cấp hỗ trợ riêng bằng cách sử dụng các hàm như công dân hạng nhất (dòng 1 và 2 trong mã) và thành phần chức năng (dòng 3)


Tại sao điều này tốt hơn (hoặc tệ hơn) so với phương pháp của OP? Và / hoặc bạn nghĩ gì về ý tưởng của OP để sử dụng một mẫu trang trí?
Kasper van den Berg

đoạn mã này tốt hơn và rõ ràng về việc đặt hàng (nén trước khi mã hóa); tránh các giao diện không mong muốn
Rag
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.